How to convert numbers to strings? - c++

I need to convert numbers between 0 and 1 billion to German words as a wstring.
I was pretty sure I got it right, but somewhere I have a mistake, and I don't see which.
For example for 1001, it should say "eintausendeins" ("onethousandone"), but instead it returns "nulleins" ("zero one").
Where am I going wrong?
wstring NumberToWords(wstring u)
{
map<int, wstring> numberWords =
{
{0, L"null"},
{1, L"eins"},
{2, L"zwei"},
{3, L"drei"},
{4, L"vier"},
{5, L"fünf"},
{6, L"sechs"},
{7, L"sieben"},
{8, L"acht"},
{9, L"neun"},
{10, L"zehn"},
{11, L"elf"},
{12, L"zwölf"},
{13, L"dreizehn"},
{14, L"vierzehn"},
{15, L"fünfzehn"},
{16, L"sechzehn"},
{17, L"siebzehn"},
{18, L"achtzehn"},
{19, L"neunzehn"},
{20, L"zwanzig"},
{30, L"dreißig"},
{40, L"vierzig"},
{50, L"fünfzig"},
{60, L"sechzig"},
{70, L"siebzig"},
{80, L"achtzig"},
{90, L"neunzig"},
{100, L"hundert"},
{1000, L"tausend"},
{1000000, L"million"},
{1000000000, L"milliarde"}
};
std::wstring result = L"";
std::wstring number = u;
if (number.empty() || number == L"0")
{
return numberWords[0];
}
std::vector<int> numberParts;
int size = number.size();
int start = size - 3;
int end = size;
while (start >= 0)
{
if (start == 0 && size % 3 != 0)
{
numberParts.push_back(stoi(number.substr(0, end - start)));
break;
}
numberParts.push_back(stoi(number.substr(start, end - start)));
end = start;
start -= 3;
}
for (int i = numberParts.size() - 1; i >= 0; i--)
{
int part = numberParts[i];
if (part >= 100) {
result += numberWords[part / 100];
result += L" ";
result += numberWords[100];
part = part % 100;
if (part > 0) {
result += L" ";
}
}
if (part >= 20)
{
result += numberWords[(part / 10) * 10];
part = part % 10;
if (part > 0) {
result += L" ";
result += numberWords[part];
}
}
else if (part > 0)
{
result += numberWords[part];
}
if (i > 0)
{
result += L" ";
if (part > 0)
{
result += numberWords[1000 * (int)pow(10, i)];
result += L"en";
}
}
}
return result;
}

This loop is incorrect
std::vector<int> numberParts;
int size = number.size();
int start = size - 3;
int end = size;
while (start >= 0)
{
if (start == 0 && size % 3 != 0)
{
numberParts.push_back(stoi(number.substr(0, end - start)));
break;
}
numberParts.push_back(stoi(number.substr(start, end - start)));
end = start;
start -= 3;
}
It should be something like
std::vector<int> numberParts;
int size = number.size();
int start = size - 3;
int end = size;
while (start > 3)
{
numberParts.push_back(stoi(number.substr(start, end - start)));
end = start;
start -= 3;
}
numberParts.push_back(stoi(number.substr(0, end - start)));
My version is completely untested code, but if you look at your version with number as "1001" you are only going round the initial loop once, consequently you only get one entry in numberParts.
Using a debugger would have shown you the problem very quickly, as would being able to 'run' the code accurately in your head (i.e. being able to see what the code you wrote actually does instead of what you hope it does). Both are essential skills for a programmer.

Related

Decremeting one from a number represent as a vector?

I am trying to decrement a number, which can be infinitely long and is represented in a vector, by 1. As a small example:
vector<int> v1 = {5, 0, 0, 0};
After subtracting one from the end, the result should be:
vector<int> v1 = {4, 9, 9, 9};
This is my current code:
int size = v1.size();
bool carry = false;
for (int i = size - 1; i > 0; i--) {
if (v1.at(i) == 0) {
v1.at(i) = 9;
if (v1.at(0) == 1) {
v1.at(0) = 0;
}
carry = true;
} else {
v1.at(i) -= 1;
carry = false;
}
}
if (carry == true && v1.at(0) == 0) {
v1.erase(v1.begin());
} else if (carry == true) {
v1.at(0) -= 1;
}
return v1;
When I test it, everything works fine, except numbers like 11119. They turn out to be 00019. Is there anything I could tweak?
It seems to me that you didn't think through the logic clearly.
Here's what needs to happen.
If the last number is 0, it needs to be changed to 9 and a carry has to be maintained.
Repeat until no carry needs to be maintained.
That logic is best implemented using a do - while loop. Here's what I came up with.
int size = v.size();
bool carry = true;
int i = size - 1;
do
{
if (v.at(i) == 0)
{
v.at(i) = 9;
}
else
{
v.at(i)--;
carry = false;
}
--i;
}
while ( carry == true && i >= 0);
Here's a complete program
#include <iostream>
#include <vector>
void test(std::vector<int> v)
{
int size = v.size();
bool carry = true;
int i = size - 1;
do
{
if (v.at(i) == 0)
{
v.at(i) = 9;
}
else
{
v.at(i)--;
carry = false;
}
--i;
}
while ( carry == true && i >= 0);
for ( auto item : v )
{
std::cout << item << " ";
}
std::cout << std::endl;
}
int main()
{
test({1, 1, 1, 1, 9});
test({5, 0, 0, 0, 0});
}
and its output
1 1 1 1 8
4 9 9 9 9
See it working at https://ideone.com/lxs1vz.
A subtraction as you tried to do, could be done like this:
#include <iterator>
std::vector<int> v1 = {5, 0, 0, 0};
for (std::vector<int>::reverse_iterator i = v1.rbegin(); i != v1.rend(); i++) {
*i -= 1;
if (*i < 0) {
*i = 9;
}
else {
break;
}
}

How to display an array dynamically

I need to create a function that displays the following:
if number is between 0 - 5 then display values 1, 2, 3, 4, 5
if number is between 5 - 10 then display values 2, 4, 6, 8, 10
if number is between 10 - 50 then display values 10, 20, 30, 40, 50
if number is between 50 - 100 then display values 20, 40, 60, 80, 100
if number is between 100 - 500 then display values 100, 200, 300, 400, 500
if number is between 500 - 1000 then display values 200, 400, 600, 800, 1000
if number is between 1000 - 5000 then display values 1000, 2000, 3000, 4000, 5000
and so on...
I'm thinking of working with 2 arrays and then multiply with 10.
int *MyFunct(int number) {
int a[5] = { 1, 2, 3, 4, 5 };
int b[5] = { 2, 4, 6, 8, 10 };
if (number >= 0 && number <= 5) {
return a;
}
else if (number > 5 && number <= 10) {
return b;
}
else if (number > 10 && number <= 50) {
a[1] *= 10;
a[2] *= 10;
a[3] *= 10;
a[4] *= 10;
a[5] *= 10;
}
.
.
.
}
Is there any possibility to do this dynamically or simpler?
You can keep your first 2 arrays. You can do this in 3 steps.
Check if number is between 10^n and 5*(10^n). If it is, use the first array. If not, use the second array.
After that multiply each number by 10^n for some n such that 10^n < number.
This can be done by a for loop to check
I would start with something like that:
std::vector<unsigned int> MyFunct(unsigned int number) {
std::vector<unsigned int> numbers = { 1,2,3,4,5 };
unsigned int factor = 1;
while(number >= 10)
{
number /= 10;
factor *= 10;
}
if(number >= 5)
{
factor *= 2;
}
for(unsigned int i = 0; i < numbers.size(); ++i)
{
numbers[i] *= factor;
}
return numbers;
}
You could also work with logarithm of base 10.
You must first note that you cannot return an automatic array. For this use case, the simplest is to just use static ones.
Then your algorithm can be reworded as:
start with the array [1, 2, 3, 4, 5]
if the number is less than the last number of the array, return the array
else multiply the array alternatively by 2 and 5
In C++ it gives:
int *MyFunc(int n) {
static const int init[] = {1, 2, 3, 4, 5}; // the initial array
static int result[5];
int& max = result[4]; // alias for the last value
// copy init to result:
for (int i=0; i<5; i++) result[i] = init[i];
// find the range of n
for (;;) {
if (n <= max) {
break;
}
// multiply alternatively by 2 and by 5
for (int i=0; i<5; i++) result[i] *= 2;
if (n <= max) {
break;
}
for (int i=0; i<5; i++) result[i] *= 5;
}
return result;
}
Simple and compact...
Here's a variant that does what you say it should do – display those outputs – rather than return an array.
It does not use any arrays at all.
(Note that the problem as stated contains overlapping intervals. I have assumed that the intervals are actually 0-5, 6-10, 11-50, 51-100, 101-500, 501-1000, and >1000.)
int factor(int x)
{
if (x > 1000)
{
return 1000;
}
if (x > 500)
{
return 200;
}
if (x > 100)
{
return 100;
}
if (x > 50)
{
return 20;
}
if (x > 10)
{
return 10;
}
if (x > 5)
{
return 2;
}
return 1;
}
void display(int x)
{
auto f = factor(x);
for (int i = 1; i <= 5; ++i)
{
std::cout << f * i << " ";
}
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
std::vector<int> test = { 1, 6, 11, 52, 103, 504, 1005 };
for (auto i: test)
{
display(i);
}
}
Output:
1 2 3 4 5
2 4 6 8 10
10 20 30 40 50
20 40 60 80 100
100 200 300 400 500
200 400 600 800 1000
1000 2000 3000 4000 5000
And a variation of factor that uses a table instead of a long chain of conditionals:
int factor(int x)
{
struct interval { int limit; int factor; };
interval intervals[] = {{1000, 1000},
{500, 200},
{100, 100},
{50, 20},
{10, 10},
{5, 2}};
for (auto i: intervals)
{
if (x > i.limit)
{
return i.factor;
}
}
return 1;
}

Fibonacci Sum of Large Numbers(Only Last Digit to be Printed)

I have been trying to come out with a solution regarding the problem of finding the last digit of the sum of large n Fibonacci series.
I have been able to pass several test cases with large n. But I'm stuck at the following case where n = 832564823476. I know it can be solved using Pisano's period but I'm unable to come out with a efficient algo. Any help would be great. Thanks.
My code that I have implemented is as follows-
#include <iostream>
using namespace std;
int calc_fib(int n) {
int fib[n+1];
fib[0]=0;
fib[1]=1;
int res = 1;
for(int i = 2; i<=n;i++){
fib[i] = (fib[i-1]%10 + fib[i-2]%10)%10;
res = res + fib[i];
}
return (res%10);
}
int main() {
int n = 0;
std::cin >> n;
std::cout << calc_fib(n) << '\n';
return 0;
}
SOLVED IT
Works on all range of inputs. It works on the following algorithm.
The idea is to notice that the last digits of fibonacci numbers also occur in sequences of length 60 (from the previous problem: since pisano peiod of 10 is 60). Irrespective of how large n is, its last digit is going to have appeared somewhere within the sequence.
Two Things apart from edge case of 10 as last digit.
Sum of nth Fibonacci series = F(n+2) -1
Then pisano period of module 10 = let n+2 mod (60) = m then find F(m) mod(10)-1
Code as follows;
#include <iostream>
using namespace std;
long long calc_fib(long long n) {
n = (n+2)%60;
int fib[n+1];
fib[0]=0;
fib[1]=1;
int res = 1;
for(int i = 2; i<=n;i++){
fib[i] = (fib[i-1]%10 + fib[i-2]%10)%10;
// res = res + fib[i];
}
// cout<<fib[n]<<"\n";
if(fib[n] == 0){
return 9;
}
return (fib[n]%10-1);
}
int main() {
long long n = 0;
std::cin >> n;
std::cout << calc_fib(n) << '\n';
return 0;
}
Actually it's even easier than Niall answer
int get_fibonacci_sum_last_digit(long long n) {
const int kPisanoSize = 60;
int rest = n % kPisanoSize;
int preparedNumbers[kPisanoSize] = {0, 1, 2, 4, 7, 2, 0, 3, 4, 8, 3,
2, 6, 9, 6, 6, 3, 0, 4, 5, 0, 6, 7, 4, 2, 7, 0, 8, 9, 8, 8, 7,
6, 4, 1, 6, 8, 5, 4, 0, 5, 6, 2, 9, 2, 2, 5, 8, 4, 3, 8, 2, 1,
4, 6, 1, 8, 0, 9, 0};
return preparedNumbers[rest];
}
If you only need to output the last digit as you said, I think you can just make use of the Pisano Period you mentioned, as for modular 10, the cycle length is only 60 and you can just pre-make an array of that 60 digits.
If you want to compute by yourself, I think you can use Matrix Exponentiation which gives you O(lg N) complexity, when calculating the matrix exponents, keep storing the temporary result modular 10. See the Matrices section for your reference.
For your function removing the array.
#include "stdafx.h"
#include <iostream>
using namespace std;
int calc_fib(long long int n) {
int fibzero = 0;
int fibone = 1;
int fibnext;
long long int res = 1;
for (long long int i = 2; i <= n; i++) {
fibnext = (fibone + fibzero) % 10;
fibzero = fibone;
fibone = fibnext;
res = res + fibnext;
}
return (res % 10);
}
int main()
{
long long int n = 0;
std::cin >> n;
std::cout << calc_fib(n) << '\n';
return 0;
}
Last digit of Fibonacci sum repeats after 60 elements.
Here the period is 60 [0-59].
So to get the last digit of n'th sum of number is the last digit of n%60'th sum of
number
#include <iostream>
#include <vector>
#include <algorithm>
int get_last_digit(int n){
std::vector<int> last_digits(60);
long long a = 0, b = 1;
last_digits[0] = 0;
last_digits[1] = 1;
long long temp, sum = 1;
// Fill last_digits vector with the first 60 sums last digits
for (int i = 2; i < 60; i++) {
temp = a+b;
a = b;
b = temp;
sum += temp;
last_digits[i] = sum%10;
}
// Now return n%60'th element
return last_digits[n%60];
}
int main(int argc, char const *argv[]) {
int n;
std::cin>>n;
std::cout << get_last_digit(n);
return 0;
}
A neat way to solve the problem (I use java). The logic is to utilize the pisano period of 10. To write down the corresponding relationship between Sum(F(n)) = F(n+2) + 1 can help a lot. tip: create a fibonacci sequence alone.
private static long getFibonacciSum(long n) {
n = (n + 2) % 60;
long[] fib = new long[(int) n + 1];
long cor;
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i <= n; i++) {
fib[i] = (fib[i - 1] + fib[i - 2]) % 10;
}
if (fib[(int) n] == 0) cor = 9;
else cor = fib[(int) n] - 1;
return cor;
}

c++ Increasing for loop increment logarithmically

I want to loop though integers like this:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, ..., 100, 200, ..., 1000, 2000, ...
I have code to do this (shown below) however it is cumbersome and not programmed generally to deal with different stopping limits:
int MAX = 10000;
for (int i = 1; i <= MAX; i++) {
cout << i << endl;
if (i >= 10 && i < 100) {
i += 9;
}
else if (i >= 100 && i < 1000) {
i+= 99;
}
else if (i >= 1000 && i < 10000) {
i += 999;
}
}
As you can see, this is very situation specified as mentioned previously - so I'd like to know of a way to code this in a more general way, as for my requirements MAX will be of the order of 10^9 so using code like above is far too impractical.
Try this code. It is more general:
int MAX = 1000000;
for (int i = 1, increment = 1, counter = 1; i <= MAX; i += increment) {
cout << i << endl;
if (counter == 10) {
increment *= 10;
counter = 1;
}
++counter;
}

fastest algorithm count number of 3 length AP in array

I want to solve this CodeChef challenge:
Suppose We are given an array A of N(of range 100,000) elements. We are to find the count of all pairs of 3 such elements 1<=Ai,Aj,Ak<=30,000 such that
Aj-Ai = Ak- Aj and i < j < k
In other words Ai,Aj,Ak are in Arithmetic Progression. For instance for Array :
9 4 2 3 6 10 3 3 10
so The AP are:
{2,6,10},{9,6,3},{9,6,3},{3,3,3},{2,6,10}
So the required answer is 5.
My Approach
What I tried is take 30,000 long arrays named past and right. Initially right contains the count of each 1-30,000 element.
If we are at ith position past stores the count of array value before i and right stores the count of array after i. I simply loop for all possible common difference in the array. Here is the code :
right[arr[1]]--;
for(i=2;i<=n-1;i++)
{
past[arr[i-1]]++;
right[arr[i]]--;
k=30000 - arr[i];
if(arr[i] <= 15000)
k=arr[i];
for(d=1;d<=k;d++)
{
ans+= right[arr[i] + d]*past[arr[i]-d] + past[arr[i] + d]*right[arr[i]-d];
}
ans+=past[arr[i]]*right[arr[i]];
}
But this gets me Time Limit Exceeded. Please help with a better algorithm.
You can greatly cut execution time if you make a first pass over the list and only extract number pairs that it is possible to have an 3 term AP between (difference is 0 mod 2). And then iterating between such pairs.
Pseudo C++-y code:
// Contains information about each beginning point
struct BeginNode {
int value;
size_t offset;
SortedList<EndNode> ends; //sorted by EndNode.value
};
// Contains information about each class of end point
struct EndNode {
int value;
List<size_t> offsets; // will be sorted without effort due to how we collect offsets
};
struct Result {
size_t begin;
size_t middle;
size_t end;
};
SortedList<BeginNode> nodeList;
foreach (auto i : baseList) {
BeginNode begin;
node.value = i;
node.offset = i's offset; //you'll need to use old school for (i=0;etc;i++) with this
// baseList is the list between begin and end-2 (inclusive)
foreach (auto j : restList) {
// restList is the list between iterator i+2 and end (inclusive)
// we do not need to consider i+1, because not enough space for AP
if ((i-j)%2 == 0) { //if it's possible to have a 3 term AP between these two nodes
size_t listOffset = binarySearch(begin.ends);
if (listOffset is valid) {
begin.ends[listOffset].offsets.push_back(offsets);
} else {
EndNode end;
end.value = j;
end.offsets.push_back(j's offset);
begin.ends.sorted_insert(end);
}
}
}
if (begin has shit in it) {
nodeList.sorted_insert(begin);
}
}
// Collection done, now iterate over collection
List<Result> res;
foreach (auto node : nodeList) {
foreach (auto endNode : node.ends) {
foreach (value : sublist from node.offset until endNode.offsets.last()) {
if (value == average(node.value, endNode.value)) {
// binary_search here to determine how many offsets in "endNode.offsets" "value's offset" is less than.
do this that many times:
res.push_back({node.value, value, endNode.value});
}
}
}
}
return res;
Here's a simple C version of the solution that takes advantage of the Ai + Ak must be even test:
#include <stdio.h>
static int arr[] = {9, 4, 2, 3, 6, 10, 3, 3, 10};
int main ()
{
int i, j, k;
int sz = sizeof(arr)/sizeof(arr[0]);
int count = 0;
for (i = 0; i < sz - 2; i++)
{
for (k = i + 2; k < sz; k++)
{
int ik = arr[i] + arr[k];
int ikdb2 = ik / 2;
if ((ikdb2 * 2) == ik) // if ik is even
{
for (j = i + 1; j < k; j++)
{
if (arr[j] == ikdb2)
{
count += 1;
printf("{%d, %d, %d}\n", arr[i], arr[j], arr[k]);
}
}
}
}
}
printf("Count is: %d\n", count);
}
and the console dribble:
tmp e$ cc -o triples triples.c
tmp e$ ./triples
{9, 6, 3}
{9, 6, 3}
{2, 6, 10}
{2, 6, 10}
{3, 3, 3}
Count is: 5
tmp e$
This more complicated version keeps a list of Aj indexed by value to go from n-cubed to n-squared (kinda).
#include <stdio.h>
#include <stdint.h>
static uint32_t arr[] = {9, 4, 2, 3, 6, 10, 3, 3, 10};
#define MAX_VALUE 100000u
#define MAX_ASIZE 30000u
static uint16_t index[MAX_VALUE+1];
static uint16_t list[MAX_ASIZE+1];
static inline void remove_from_index (int subscript)
{
list[subscript] = 0u; // it is guaranteed to be the last element
uint32_t value = arr[subscript];
if (value <= MAX_VALUE && subscript == index[value])
{
index[value] = 0u; // list now empty
}
}
static inline void add_to_index (int subscript)
{
uint32_t value = arr[subscript];
if (value <= MAX_VALUE)
{
list[subscript] = index[value]; // cons
index[value] = subscript;
}
}
int main ()
{
int i, k;
int sz = sizeof(arr)/sizeof(arr[0]);
int count = 0;
for (i = 0; i < sz - 2; i++)
{
for (k = i; k < sz; k++) remove_from_index(k);
for (k = i + 2; k < sz; k++)
{
uint32_t ik = arr[i] + arr[k];
uint32_t ikdb2 = ik / 2;
add_to_index(k-1); // A(k-1) is now a legal middle value
if ((ikdb2 * 2) == ik) // if ik is even
{
uint16_t rover = index[ikdb2];
while (rover != 0u)
{
count += 1;
printf("{%d, %d, %d}\n", arr[i], arr[rover], arr[k]);
rover = list[rover];
}
}
}
}
printf("Count is: %d\n", count);
}
and the dribble:
tmp e$ cc -o triples triples.c
tmp e$ ./triples
{9, 6, 3}
{9, 6, 3}
{2, 6, 10}
{2, 6, 10}
{3, 3, 3}
Count is: 5
tmp e$