summaryrefslogblamecommitdiffstats
path: root/mat/euler/17/angnum.c
blob: 2f16d753abc5359aa059f34f53ba9df7d8a270ca (plain) (tree)



















                                       
                                 
















                                   



                                     
                             
                                  


                              
                                                                                                                                              
                                                                               









                                                                                                                                                                                                  







                                                                                   



                                                                 












                                                                                         
                                                                           






                                                                         
                                                                               
                                                                     
                                  
                                        




























                                                                                             
                                        


                                                             
         


                                 

                 
                         




                                                                                                                                      
                                                     
                                                
                                         
                                   
                              
 
      
#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