summaryrefslogtreecommitdiffstats
path: root/mat/euler/17/angnum.c
blob: 2f16d753abc5359aa059f34f53ba9df7d8a270ca (plain) (blame)
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
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* definiramo jezik - ZAČETEK */
#define J_0			"zero"
#define J_1			"one"
#define J_2			"two"
#define J_3			"three"
#define J_4			"four"
#define J_5			"five"
#define J_6			"six"
#define J_7			"seven"
#define J_8			"eight"
#define J_9			"nine"
#define J_10		"ten"
#define J_11		"eleven"
#define J_12		"twelve"
#define J_13		"thirteen"
#define J_14		"fourteen"
#define J_15		"fifteen"
#define J_16		"sixteen"
#define J_17		"seventeen"
#define J_18		"eighteen"
#define J_19		"nineteen"
#define J_20		"twenty"
#define J_30		"thirty"
#define J_40		"forty"
#define J_50		"fifty"
#define J_60		"sixty"
#define J_70		"seventy"
#define J_80		"eighty"
#define J_90		"ninety"
#define J_1h		"hundred"
#define J_1k		"thousand"
#define J_1M		"million"
#define J_1G		"billion"
#define J_1T		"trillion"
#define J_1P		"quadrillion"
#define J_1E		"quintillion"
#define J_1Z		"sextillion"
#define J_1Y		"septillion"
#define J_AND		"and"
#define J_NEG		"negative"
#define J_EMPTY	""
/* definiramo jezik - KONEC */
#define MX_NS_L	1337 
char * j_enice[] = { J_EMPTY, J_1, J_2, J_3, J_4, J_5, J_6, J_7, J_8, J_9, J_10, J_11, J_12, J_13, J_14, J_15, J_16, J_17, J_18, J_19, J_20 };
char * j_power[] = { J_EMPTY, J_1k, J_1M, J_1G, J_1T, J_1P, J_1E, J_1Z, J_1Y };
char * j_desetice[] = { J_EMPTY, J_10, J_20, J_30, J_40, J_50, J_60, J_70, J_80, J_90 };

unsigned long long int na(unsigned long long int a, unsigned long long int b) {
	unsigned long long int c = 1; /* jebeš math.h ke nima funkcije za intager */
	for (; b > 0; b--) {					/* potenciranje															*/
		c = c * a;
	}
	return c;
}

/* private_angnum : size_t (število zapisanih bajtov, -1 ob propadu sveta)
 *	n: lluint: številka, ki naj jo zapišemo
 *	s: pointer to allocatanega spomina, kamor zapišemo string
 *	l: število bajtov allocatanega spomina za string, IZključno zadnjega '\0'
 * alocirati morate vsaj en bajt več od l
 * string bo mogoče avtomatsko null terminiran, vseeno ga raje dajte še sami
 * UPORABLJAJTE RAJE angnum NAMESTO private_angnum */
size_t private_angnum (unsigned long long int n, char * s, int l) {
	unsigned int i = 0; // Index Iteracij
	int z = 0; // Zapisanih
	if (n <= 20) { // "thirteen", namesto 0 je prazen string 
		z = snprintf(s, l, "%s", j_enice[n]);
		return z;
	}
	if (n <= 99) { // && n > 20 // "forty-one" ali "thirty"
		z = snprintf(s, l, "%s", j_desetice[n / 10]); // intdiv je floor
		if (z < l && n % 10 != 0) s[z++] = '-';
		return z + (n % 10 != 0 ? snprintf(s+z, l-z, "%s", j_enice[n % 10]) : 0);
	}
 	if (n <= 999) { // && n > 99
		z = snprintf(s, l, "%s ", j_enice[n/100]); // "one "
		z = z + snprintf(s+z, l-z, "%s", J_1h); // "hundred"
		if (n % 100 != 0) {
			if (z < l) s[z++] = ' ';
			z = z + snprintf(s+z, l-z, "%s ", J_AND); // "and "
			return z + private_angnum(n-(n/100)*100, s+z, l-z);
		} else {
			return z;
		}
	} // sedaj je n > 99 && n < 1e21
	for (i = 3; i <= 21; i=i+3) // sedaj iščemo največjo tisočico
		if (n / na(10, i) <= 999) // zadnja tisočica
			break;
	z = private_angnum((n/na(10, i)), s, l-z); // "three hundred forty-two"
	z = z + snprintf(s+z, l-z, " %s", j_power[i/3]); // "million"
	if (n-(n/na(i, 10)) > 0) {
		if (z < l) s[z++] = ' ';
		z = z + private_angnum(n-(n/na(10, i)*na(10, i)), s+z, l-z);
	}
	return z;
}
/*
 * angnum(n, s, sizeof) : size_t napisanih bajtov, vključno z nul bajtom
 * n je celo, ki ga je treba napisati. lahko je 0, negativno ali pozit..
 * s je pointer do char, kamor naj se piše številka.
 * sizeof je velikost alocatanega spomina za s, vključno z nul bajtom, naj bo>0.
 * funkcija vrne število napisanih bajtov ali pa 0 v primeru napake.
 * če je vrednost 0, je vsebina spomina od s do s+sizeof neopredeljena.
 * število se zapiše v britanskem formatu, s pomišljajem in and.
 * niz je končan z nul bajtom in pripravljen na tiskanje.
 * četudi je string uspešno napisan, lahko funkcija odvrne 0, če se bliža
 * 		omejitvi prostora sizeof. prav tako, četudi je dovolj prostora,
 * 		lahko funkcija napiše napačno vrednost v s, če se bliža omejitvi, zato je
 * 		nastavljen check, da funkcija odvrne 0, če je omejitev prostora 10+-2
 * 		bajtov stran od napisanega.
 * funkcija naj ne bi pisala preko omejitve sizeof.
 * */
size_t angnum (long long int n, char * s, int l) {
	size_t z = 0;
	size_t i = 0;
	if (n == 0) {
		z = snprintf(s, l, "%s", J_0);
		return z;
	}
	if (n < 0) {
		z = snprintf(s, l, "%s", J_NEG);
		if (z < l) s[z++] = ' ';
		z = z + private_angnum(abs(n), s+z, (l-z)-1);
	} else {
		z = z + private_angnum(n, s+z, (l-z)-1);
	}
	if (z < l) s[z++] = '\0';
	if (l - z < 10)
		return 0;
	return z;
}
#ifndef DISABLE_LIB_TESTS
int main (int argc, char ** argv) {
	if (argc != 1+1) {
		fprintf(stderr, "uporaba: %s <stevilka>\nprimer, ki napiše \"four hundred and twenty\": %s 420\n", argv[0], argv[0]);
		return 1;
	}
	long long int n = strtoll(argv[1], NULL, 10);
	char * s = malloc(sizeof(char)*MX_NS_L);
	size_t r = angnum(n, s, MX_NS_L);
	fprintf(stdout, "%s\n", s);
	return r == 0 ? 2 : 0;
}
#endif