-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpe017.cpp
More file actions
151 lines (130 loc) · 5.06 KB
/
pe017.cpp
File metadata and controls
151 lines (130 loc) · 5.06 KB
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
#include <iostream>
#include <cmath>
#include <sstream>
#include <tuple>
#include "pe.h"
/**
* Takes in a positive integer (1 <= number < 1000) and returns the human string
* as well as the count of letters.
* Example: 128 would return <24, "one hundred and twenty eight">
**/
template<typename T>
std::tuple<size_t, std::string> char_count_and_string_e2(T number) {
if (number < 0 || number >1000) {
std::cerr << "ERROR: " << number << std::endl;
throw std::invalid_argument("Input must be between 0 and 999 inclusive");
}
if (number == 0) {
return std::make_tuple(0, "");
}
std::string u20[19] = {"one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
"nineteen"};
std::string tens[8] = {"twenty", "thirty", "forty", "fifty", "sixty", "seventy",
"eighty", "ninety"};
std::string hundred = "hundred";
std::string and_string = "and";
size_t count = 0;
std::stringstream stream;
T remainder = number;
T temp;
if (remainder >= 100) {
temp = T(remainder/100);
remainder = remainder % 100;
count += u20[temp-1].length() + hundred.length();
stream << u20[temp-1] << " " << hundred;
if (remainder >= 1) {
count += and_string.length();
stream << " " << and_string << " ";
}
}
while (remainder >= 1) {
if (remainder >=20 && remainder < 100) {
temp = T(remainder/10);
remainder = remainder % 10;
count += tens[temp-2].length();
stream << tens[temp-2];
// only add a space if we need to finish the number
if (remainder >= 1) {
stream << " ";
}
} else if (remainder >= 1 && remainder < 20) {
count += u20[remainder-1].length();
stream << u20[remainder-1];
remainder = 0;
}
}
return std::make_tuple(count, stream.str());
}
/**
* Takes in a positive integer (1 <= number < 1*10^63) and returns the human string
* as well as the count of letters.
* Example: 128 would return <24, "one hundred and twenty eight">
* Example: 100003450000 would return <56, "one hundred billion three million four hundred and fifty thousand">
**/
template<typename T>
std::tuple<size_t, std::string> char_count_and_string_ex3(T number) {
// These are all of the groupings in increments of 10^3 in wikipedia
std::string e3s[21] = {
"thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion",
"octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
"quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion"};
size_t count = 0;
std::stringstream stream;
double logval;
T section, section_scalar, section_value;
while (number >= 1) {
// isolate the most significant "section" (named triplet group)
logval = log10(number);
section = floor(logval/3);
section_scalar = pow(10, section*3);
section_value = number / section_scalar;
std::tuple<size_t, std::string> section_tuple = char_count_and_string_e2<T>(section_value);
count += std::get<0>(section_tuple);
stream << " " << std::get<1>(section_tuple);
number -= (section_value * section_scalar);
if (section >=1) {
count += e3s[section-1].length();
stream << " " << e3s[section-1];
}
}
return std::make_tuple(count, stream.str());
}
/**
* Specifically for pe017: loop from 1 through [number] and sum the character count for all human-written words.
*/
size_t get_looped_letter_count(int number) {
size_t counter = 0;
std::tuple<size_t, std::string> count_and_string;
for (int i = 1; i <= number; ++i) {
count_and_string = char_count_and_string_ex3<int>(i);
counter += std::get<0>(count_and_string);
//std::cout << i << ":\t" << std::get<0>(count_and_string) << "\t" << counter << "\t" << std::get<1>(count_and_string) << std::endl;
}
return counter;
}
/**
* Simple util function to print out a number, it's english form, and the character count.
*/
template<typename T>
void printout(T number) {
std::tuple<size_t, std::string> result = char_count_and_string_ex3<T>(number);
std::cout << number << "\t" << std::get<0>(result) << "\t" << std::get<1>(result) << std::endl;
}
class pe017 : public pe_base {
void run_test() {
//check("017", 19, int(get_looped_letter_count(5)));
check("017", 21124, int(get_looped_letter_count(1000)));
}
};
int main(int argc, char** argv) {
/*
printout<long long>(100003450000LL);
printout<long long>(123456789123LL);
*/
pe017 test;
test.go();
std::cout << test.get_message() << std::endl;
return test.exit_code();
}