summaryrefslogtreecommitdiffstats
path: root/main.c
blob: 9ccdfbdf4ac1b5311aa757b3046f3a800e618deb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*	Copyright (C) 2020 Gentoo-libre Install

	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define DEFAULT_SIZE 40 //default size, not too big, not too small
bool negative = false;

//modulo() modulo to return remainder instead of remainder, may not work if N is negative
long long modulo(long long x,long long N)
{
    return (x % N + N) % N;
}

//powq(): square roots
long long powq(long long number, long long power)
{
int result = 1;//result int, 1 by default
if (!power){return 1;}//if to the power of 0, return 1
while(power)//loop until all powers have been calculated
        {
	result *= number;//in the end result=number*number*number*etc until power is reached
        --power;//--power since a power has been calculated
        }
return result;
}

//mod(): Converts ASCII string to int and calculates modulus while showing working.
void mod(char s[], char *result, int length)
{
if (s[0] == '\0'){printf("Error\n"); return;}//catch case of blank input

char *modChar = strstr(s, "m");//find place of 'm' in string (marker for mod)
if (!modChar){printf("Error\n"); return;}//if m not found, return blank string
++modChar;//point to the character above 'm'

int power = 0;  //int to store the power.
while(s[power] != 'm'){++power;}//increment power for however many non-null chars in the string.
--power;//The correct power is actually one less than above returns

int i = 0;//counter int
long long integer = 0;//where the converted int is stored
while (s[i] != 'm')//convert the string of decimal numbers into a int
	{
	if (s[i] >= '0' && s[i] <= '9'){integer += ((s[i] - '0') * powq(10,power));}//integer = integer + ([char converted to number] * (10^[position of number in string]))

	++i;
	--power;//Deincrement the power. E.g. ([charvalue]*(10^3))+([nextcharvalue]*(10^2)) etc
	}
if (negative){integer = -integer;}


int modPower = 0; //int to store the mod power.
while(modChar[modPower] != '\0'){++modPower;}//increment power for however many non-null chars in the string.
--modPower;//The correct power is seems to be 2 less than above returns (???)

i = 0;
long long modulus = 0;//where the converted modulus is stored
while (modChar[i] != '\0')//convert the string of decimal numbers into a  int
	{
	if (modChar[i] >= '0' && modChar[i] <= '9'){modulus += ((modChar[i] - '0') * powq(10,modPower));}//modulus = modulus + ([char converted to number] * (10^[position of number in string]))

	++i;
	--modPower;//Deincrement the power. E.g. ([charvalue]*(10^3))+([nextcharvalue]*(10^2)) etc
	}

//printf("Number: %lld\n", integer);

//printf("Modulus: %lld\n", modulus);

double fraction = (double)integer;//the modulus working steps are done on fraction since they require decimal points

if (!modulus){printf("Modulus 0 is undefined\n"); return;}

i = 0;
if (!negative)
	{
	//should be pretty self explainatory
	fraction /=modulus;
	printf("0. %lld / %lld = %lf\n", integer, modulus, fraction);

	printf("1. %lf - %lld = %lf\n", fraction, integer/modulus, fraction - (integer/modulus));
	fraction -= (integer/modulus);

	printf("2. %lf * %lld = %lf\n", fraction, modulus, fraction*modulus);
	}
else
	{
	printf("int r = integer%%modulus;\nreturn r<0 ? r+m : r;\n"); negative = false;
	}

//just solve it directly
//printf("Answer: %u\n", integer % modulus);
printf("Answer: %lld\n", modulo(integer,modulus));
}

int main(int argc, char *argv[])
{
if ((argv[1]) && (argv[1][0] == '-'))
	{
	printf("Usage: [firstnum] mod [secondnum]\n");
	printf("Or: [firstnum]m[secondnum]\n");
	printf("This program solves modulus with working.\n");
	printf("Ctrl+D to exit\n");
	printf("Licence: AGPLv3\n");
	return 0;
	}

char input[DEFAULT_SIZE];//input string is DEFAULT_SIZE in length

//result string
char *result = malloc(DEFAULT_SIZE*sizeof(char));
if (!result){printf("Malloc failed!\n"); return 1;}
result[DEFAULT_SIZE-1]='\0';//add null terminating char

int i;
nextnum: i=0;
char *character = fgets(input, DEFAULT_SIZE, stdin);
if (!character){free(result); exit(0);}//exit if EOF (fgets() returns -1 on EOF or error)
character = strstr(input,"\n");//try to find the newline in the input so it can be overwritten
if (!character){printf("Input too long\n"); while(getchar() != '\n'); goto nextnum;}//if more than 40 chars were read, input was too long
character = '\0'; //overwrite newline with null char

//strip out invalid chars from the input string

if (input[0] == '-'){negative = true;}

int j;//another counter variable
for (i=0; input[i] != '\0'; ++i)
        {
        if ((input[i] < '0')||(input[i] > '9') && (input[i] != 'm') )//if input[i] is an invalid character
                {
                j=i;
                while(input[j] != '\0'){input[j++] = input[j+1];}//shift all characters above left, overwriting the character
                --i;//deincrement i, since the string was just shrunk by one and the one just above could indeed be a matching char
                }
        }

//printf("Input: %s\n", input);

mod(input, result, DEFAULT_SIZE-1);

//printf("Result: %s\n", result);

goto nextnum;

//this wont be reached, but included anyway in case the above goto is removed
free(result);

return 0;
}