What I have tried so far ...
start_hour = 7
start_minute = 0 * 0.01
end_hour = 17
end_minute = 45 * 0.01
step_time = 25
start_time = start_hour + start_minute
end_time = end_hour + end_minute
if step_time > 59
step_time = 1 if step_time == 60
step_time = 1.3 if step_time == 90
step_time = 2 if step_time == 120
else
step_time *= 0.01
end
hours = []
(start_time..end_time).step(step_time).map do |x|
next if (x-x.to_i) > 0.55
hours << '%0.2f' % x.round(2).to_s
end
puts hours
If I enter the step interval 0, 5, 10, 20, I can get the time interval I want. But if I enter 15, 25, 90, I can't get the right range.
You currently have:
end_hour = 17
end_minute = 45 * 0.01
end_time = end_hour + end_minute
#=> 17.45
Although 17.45 looks like the correct value, it isn't. 45 minutes is 3 quarters (or 75%) of an hour, so the correct decimal value is 17.75.
You could change your code accordingly, but working with decimal hours is a bit strange. It's much easier to just work with minutes. Instead of turning the minutes into hours, you turn the hours into minutes:
start_hour = 7
start_minute = 0
start_time = start_hour * 60 + start_minute
#=> 420
end_hour = 17
end_minute = 45
end_time = end_hour * 60 + end_minute
#=> 1065
The total amount of minutes can easily be converted back to hour-minute pairs via divmod:
420.divmod(60) #=> [7, 0]
1065.divmod(60) #=> [17, 45]
Using the above, we can traverse the range without having to convert the step interval:
def hours(start_time, end_time, step_time)
(start_time..end_time).step(step_time).map do |x|
'%02d:%02d' % x.divmod(60)
end
end
hours(start_time, end_time, 25)
#=> ["07:00", "07:25", "07:50", "08:15", "08:40", "09:05", "09:30", "09:55",
# "10:20", "10:45", "11:10", "11:35", "12:00", "12:25", "12:50", "13:15",
# "13:40", "14:05", "14:30", "14:55", "15:20", "15:45", "16:10", "16:35",
# "17:00", "17:25"]
hours(start_time, end_time, 90)
#=> ["07:00", "08:30", "10:00", "11:30", "13:00", "14:30", "16:00", "17:30"]
I am not sure how to attack this problem... I tried many things, and it seems to be that it shouldn't be so difficult, but not getting there...
Is it possible to create a function "series ( _x )", that produces this :
The function for example should be myfunction( 11 ) => 211
The terms become suffix for the next terms. See below picture for more clarity. The boxes with same color gets repeated. So, we could just keep prepending 1 and 2 for previous results.
Code(In java):
public class Solution {
public static void main(String[] args) {
List<String> ans = solve(10);
for(int i=0;i<ans.size();++i) System.out.println(ans.get(i));
}
private static List<String> solve(int terms){
List<String> ans = new ArrayList<>();
String[] digits = new String[]{"1","2"};
ans.add("1");
if(terms == 1) return ans;
ans.add("2");
if(terms == 2) return ans;
List<String> final_result = new ArrayList<>();
final_result.addAll(ans);
terms -= 2;//since 2 numbers are already added
while(terms > 0){
List<String> temp = new ArrayList<>();
for(String s : digits){
for(int j=0;j<ans.size() && terms > 0;++j){
temp.add(s + ans.get(j));
terms--;
}
}
ans = temp;
final_result.addAll(ans);
}
return final_result;
}
}
This hint should help you... It isn't quite binary, but it is close. Let me know if you need any further help
0 -> - -> -
1 -> - -> -
10 -> 0 -> 1
11 -> 1 -> 2
100 -> 00 -> 11
101 -> 01 -> 12
110 -> 10 -> 21
111 -> 11 -> 22
1000 -> 000 -> 111
1001 -> 001 -> 112
1010 -> 010 -> 121
1011 -> 011 -> 122
1100 -> 100 -> 211
1101 -> 101 -> 212
1110 -> 110 -> 221
1111 -> 111 -> 222
Edit: I didn't like the way I ordered the columns, so I swapped 2 and 3
Python approach
First thing that we need to do is produce binary strings
in Python this can be done with bin(number)
However this will return a number in the form 0b101
We can easily strip away the 0b from the beginning though by telling python that we dont want the first two characters, but we want all the rest of them. The code for that is: bin(number)[2:] left side of the : says start two spaces in, and since the right side is blank go to the end
Now we have the binary numbers, but we need to strip away the first number. Luckily we already know how to strip away leading characters so change that line to bin(number)[3:].
All that is left to do now is add one to every position in the number. To do that lets make a new string and add each character from our other string to it after incrementing it by one.
# we already had this
binary = bin(user_in + 1)[3:]
new = ""
for char in binary:
# add to the string the character + 1
new += str(int(char) + 1)
And we are done. That snippet will convert from decimal to whatever this system is. One thing you might notice is that this solution will be offset by one (2 will be 1, 3 will be 2) we can fix this by simply adding one to user input before we begin.
final code with some convenience (a while loop and print statement)
while True:
user_in = int(input("enter number: "))
binary = bin(user_in + 1)[3:]
new = ""
for char in binary:
new += str(int(char) + 1)
print(user_in, "\t->\t", binary, "\t->\t", new)
According to A000055
We should perform 3 steps:
Convert value + 1 to base 2
Remove 1st 1
Add 1 to the rest digits
For instance, for 11 we have
Converting 11 + 1 == 12 to binary: 1100
Removing 1st 1: 100
Adding 1 to the rest digits: 211
So 11 has 211 representation.
C# code:
private static String MyCode(int value) =>
string.Concat(Convert
.ToString(value + 1, 2) // To Binary
.Skip(1) // Skip (Remove) 1st 1
.Select(c => (char)(c + 1))); // Add 1 to the rest digits
Demo:
var result = Enumerable
.Range(1, 22)
.Select(value => $"{MyCode(value),4} : {value,2}");
Console.Write(string.Join(Emvironment.NewLine, result));
Outcome:
1 : 1
2 : 2
11 : 3
12 : 4
21 : 5
22 : 6
111 : 7
112 : 8
121 : 9
122 : 10
211 : 11
212 : 12
221 : 13
222 : 14
1111 : 15
1112 : 16
1121 : 17
1122 : 18
1211 : 19
1212 : 20
1221 : 21
1222 : 22
In VB.NET, showing both the counting in base-3 and OEIS formula ways, with no attempts at optimisation:
Module Module1
Function OEIS_A007931(n As Integer) As Integer
' From https://oeis.org/A007931
Dim m = Math.Floor(Math.Log(n + 1) / Math.Log(2))
Dim x = 0
For j = 0 To m - 1
Dim b = Math.Floor((n + 1 - 2 ^ m) / (2 ^ j))
x += CInt((1 + b Mod 2) * 10 ^ j)
Next
Return x
End Function
Function ToBase3(n As Integer) As String
Dim s = ""
While n > 0
s = (n Mod 3).ToString() & s
n \= 3
End While
Return s
End Function
Function SkipZeros(n As Integer) As String
Dim i = 0
Dim num = 1
Dim s = ""
While i < n
s = ToBase3(num)
If s.IndexOf("0"c) = -1 Then
i += 1
End If
num += 1
End While
Return s
End Function
Sub Main()
Console.WriteLine("A007931 Base3 ITERATION")
For i = 1 To 22
Console.WriteLine(OEIS_A007931(i).ToString().PadLeft(7) & SkipZeros(i).PadLeft(7) & i.ToString().PadLeft(11))
Next
Console.ReadLine()
End Sub
End Module
Outputs:
A007931 Base3 ITERATION
1 1 1
2 2 2
11 11 3
12 12 4
21 21 5
22 22 6
111 111 7
112 112 8
121 121 9
122 122 10
211 211 11
212 212 12
221 221 13
222 222 14
1111 1111 15
1112 1112 16
1121 1121 17
1122 1122 18
1211 1211 19
1212 1212 20
1221 1221 21
1222 1222 22
I am looking for an efficient algorithm for the following problem:
There is an array with values, i.e. (note that index 0 is omitted on purpose)
Index 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Value 17, 12, 5, 22, 3, 12, 6, 13, 7, 0, 2, 15
What I need to find is a subset of indices under these constraints:
The number of indices is constant (i.e. 3)
The sum of indices is constant (i.e. 20)
Each index may only appear once (so [2, 9, 9] is not a valid solution)
The sum of values is maximum.
For example if the subset length is 3 and the sum is 20, all possible solutions would be
Indices: [1, 7, 12] Sum of values: 17 + 6 + 15 = 38
Indices: [1, 8, 11] Sum of values: 17 + 13 + 2 = 32
Indices: [1, 9, 10] Sum of values: 17 + 7 + 0 = 24
Indices: [2, 6, 12] Sum of values: 12 + 12 + 15 = 39
Indices: [2, 7, 11] Sum of values: 12 + 6 + 2 = 20
Indices: [2, 8, 10] Sum of values: 12 + 13 + 0 = 25
Indices: [3, 5, 12] Sum of values: 5 + 3 + 15 = 23
Indices: [3, 6, 11] Sum of values: 5 + 12 + 2 = 19
Indices: [3, 7, 10] Sum of values: 5 + 6 + 0 = 11
Indices: [3, 8, 9] Sum of values: 5 + 13 + 7 = 25
Indices: [4, 5, 11] Sum of values: 22 + 3 + 2 = 27
Indices: [4, 6, 10] Sum of values: 22 + 12 + 0 = 34
Indices: [4, 7, 9] Sum of values: 22 + 6 + 7 = 35
Indices: [5, 6, 9] Sum of values: 3 + 12 + 7 = 22
Indices: [5, 7, 8] Sum of values: 3 + 6 + 13 = 22
of which [2, 6, 12] is the optimal solution because it has the maximum sum of values.
At the moment I run through all possible combinations using a slightly modified partition algorithm which grows exponentially as the sum of indices grows, so I wonder if there is any better way?
Solution O(I.S.K)
Let's do some naming first:
I is the greatest index (12 in your example)
S is the sum of values whose indices are selected (20 in your example)
K is the number of selected indices
V[] the array of values linked to the indices
maxsum(s, i, k) the maximal sum reachable by using k indices, all differents, whose value is less than or equal to i and whose sum is s.
Then you want to find maxsum(S, I, K)
Your problem exhibits some good properties:
optimal sub-structure
redundant sub-problems
For instance, when trying to compute maxsum(s, i, k) I can either not use index i, in which case the value is maxsum(s, i-1, k). Or I could use index i. In this case, I want to solve the sub-problem: what is the maximum sum reachable by indices less than or equal to i-1 and whose sum is s-i using k-1 such indices. This is the value: V[i] + maxsum(s-i, i-1, k-1).
As we want to reach the maximal sum we end up having: (Edit: corrected maxsum(s-i, i-1, k) to maxsum(s-i, i-1, k-1))
maxsum(s, i, k) = max{ maxsum(s, i-1, k) ; V[i] + maxsum(s-i, i-1, k-1) }
This is typical of a problem solvable by dynamic programming.
Here is an example C++ program solving the problem in O(I.S.K) (space and time).
We can improve the space complexity to O(I.S) at the price of a bigger time complexity: O(I.S.K²).
How to use the program
g++ -std=c++14 -g -Wall -O0 dp.cpp -o dp
./dp input.txt
Where input.txt is a file with the following format:
first line contains three integers: I S K
second line contains I integers, the values of the indices
Example run
---- K=1 ----
17 12 5 22 3 12 6 13 7 0 2 15
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12]
[ 1] 17 17 17 17 17 17 17 17 17 17 17 17
[ 2] 12 12 12 12 12 12 12 12 12 12 12
[ 3] 5 5 5 5 5 5 5 5 5 5
[ 4] 22 22 22 22 22 22 22 22 22
[ 5] 3 3 3 3 3 3 3 3
[ 6] 12 12 12 12 12 12 12
[ 7] 6 6 6 6 6 6
[ 8] 13 13 13 13 13
[ 9] 7 7 7 7
[10] 0 0 0
[11] 2 2
[12] 15
[13]
[14]
[15]
[16]
[17]
[18]
[19]
[20]
---- K=2 ----
17 12 5 22 3 12 6 13 7 0 2 15
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12]
[ 1]
[ 2] 12 12 12 12 12 12 12 12 12 12 12
[ 3] 29 29 29 29 29 29 29 29 29 29 29
[ 4] 22 22 22 22 22 22 22 22 22 22
[ 5] 17 39 39 39 39 39 39 39 39 39
[ 6] 34 34 34 34 34 34 34 34 34
[ 7] 27 27 29 29 29 29 29 29 29
[ 8] 8 24 24 24 24 24 24 24
[ 9] 25 25 25 30 30 30 30 30
[10] 34 34 34 34 34 34 34
[11] 15 28 28 28 28 28 28
[12] 9 35 35 35 35 35
[13] 18 18 29 29 29 32
[14] 25 25 25 25 27
[15] 19 19 19 24 24
[16] 13 13 13 37
[17] 20 20 20 20
[18] 13 13 27
[19] 7 15 21
[20] 9 28
---- K=3 ----
17 12 5 22 3 12 6 13 7 0 2 15
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12]
[ 1]
[ 2]
[ 3]
[ 4]
[ 5] 17 17 17 17 17 17 17 17 17 17
[ 6] 34 34 34 34 34 34 34 34 34 34
[ 7] 51 51 51 51 51 51 51 51 51
[ 8] 44 44 44 44 44 44 44 44 44
[ 9] 39 39 41 41 41 41 41 41 41
[10] 42 42 42 42 42 42 42 42
[11] 37 51 51 51 51 51 51 51
[12] 30 46 46 46 46 46 46 46
[13] 39 40 52 52 52 52 52
[14] 20 35 47 47 47 47 47
[15] 37 37 42 42 42 42 44
[16] 31 37 37 37 41 41
[17] 40 40 40 40 40 54
[18] 21 47 47 47 47 49
[19] 41 41 41 41 44
[20] 22 35 35 35 39
index: 12 sum: 20
index: 6 sum: 8
index: 2 sum: 2
max sum: 39
The source code
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <limits>
#include <valarray>
#include <vector>
using namespace std;
auto const INF = numeric_limits<double>::infinity();
struct matrix {
matrix(size_t rows, size_t cols, double value)
: cells(value, rows*cols)
, rows(rows)
, cols(cols)
, value(value)
{}
double& operator() (int r, int c)
{
if(r < 0 || c < 0)
return value;
return cells[r*cols+c];
}
valarray<double> cells;
size_t rows;
size_t cols;
double value;
};
int main(int argc, char* argv[]) {
if(argc > 1)
freopen(argv[1], "r", stdin);
// I: max index
// S: sum of indices
// K: number of indices in the sum S
int I, S, K;
cin >> I >> S >> K;
// load values
vector<double> V(I+1, 0);
for(int i=1; i<=I; ++i)
cin >> V[i];
// dynamic programming:
// --------------------
// maxsum(i, s, k) is the maximal sum reachable using 'k' indices, less
// than or equal to 'i', all differents, and having a sum of 's'
//
// maxsum(i, s, k) =
// -oo if i > s
//
// -oo if i < s && k == 1
//
// V[s] if i >= s && s <= I && k == 1
// -oo if (i < s || s > I) && k == 1
//
// max { V[i] + maxsum(i-1, S-i, k-1), maxsum(i-1, S, k) }
vector<matrix> maxsum(K+1, matrix(S+1, I+1, -INF));
// initialize K=1
for(int s=0; s<=I && s<=S; ++s) {
for(int i=s; i<=I; ++i) {
maxsum[1](s, i) = V[s];
}
}
// K > 1
for(int k=2; k<=K; ++k) {
for(int s=2; s<=S; ++s) {
for(int i=1; i<=I; ++i) {
auto l = V[i] + maxsum[k-1](s-i, i-1);
auto r = maxsum[k](s, i-1);
maxsum[k](s, i) = max(l, r);
}
}
}
// display the whole dynamic programming tables (optional)
for(int k=1; k<=K; ++k) {
cout << "---- K=" << k << " ----\n";
cout << " ";
for(int i=1; i<=I; ++i) {
cout << setw(3) << V[i] << ' ';
}
cout << '\n';
cout << " ";
for(int i=1; i<=I; ++i) {
cout << '[' << setw(2) << i << ']';
}
cout << '\n';
for(int s=1; s<=S; ++s) {
cout << '[' << setw(2) << s << "] ";
for(int i=1; i<=I; ++i) {
if(maxsum[k](s, i) == -INF) {
cout << " ";
} else {
cout << setw(3) << maxsum[k](s, i) << ' ';
}
}
cout << '\n';
}
}
// output the indices belonging to the solution by working backward in the
// dynamic programming tables
int t_S = S;
int t_I = I;
for(int k=K; k>=1; --k) {
if(t_I <= 0 || t_S <= 0) {
cout << "error...\n";
break;
}
auto m = maxsum[k](t_S, t_I);
int i;
for(i=t_I; i>=1; --i) {
if(maxsum[k](t_S, i) != m)
break;
}
cout << "index: " << setw(3) << (i+1) << ' ';
cout << "sum: " << setw(3) << t_S << '\n';
t_I = i;
t_S = t_S - i - 1;
}
cout << "max sum: " << maxsum[K](S, I) << '\n';
}
Take the arrays, and sort them by value instead of by index (keeping the index-value pairs preserved). Now, starting at the end of the array, take the last k numbers in the indices array, where k is the number of indices you have to have, and sum them up. If it equals the desired sum, great- you are done. If not, take note of the difference (desired sum - actual sum), and add that to the (n - k)th index. Find that index in the index array (ordered by value, mind you), now find your new sum of values (you can optimize this by subtracting out the old index's value and add the new one, instead of recomputing the sum of all k values).
You now have one valid solution, and a lower bound. You know the indices of the rest of the valid solution that can even possibly beat this score must come after the smallest index's value in the value-sorted array. That is:
Both sorted by value-
indices: | bunch of indices | index we found | more | k-1 'random' indices |
values: | bunch of values | value for ^ | more | k-1 largest values |
So we only have to search 'more' and the k-1 largest values for valid indices that satisfy the criteria and also have values that form a larger sum. To do this, we rinse and repeat, moving the smallest of the (n-k-1) elements backwards one, so we effectively try all combination of these elements, but in the order of decreasing subset-sums of our set of k elements. This allows us to continually narrow the space we search as we find larger sums, because know for certain that any sum that contains a smaller value than that of best solution will have a smaller sum (because the rest of the set is already as large as possible).
Pseudo Code:
pair_array = input() // each pair consists of index and value
sort_by_value(pair_array)
best_sum = 0
markers = [n - (k-1) .. n] // mark the k-1 indices being summed
while True:
sum_of_indices = sum_indices(pair_array[markers])
value_sum = sum_value(pair_array[markers])
if pair_array.contains(desired_sum - sum_of_indices): // this lets us effectively reduce our search by a factor of N, given contains uses a hashtable
value_sum += pair_array(pair_array.index(desired_sum - sum_of_indices)).value
if value_sum > best_sum:
best_sum = value_sum
pair_array.remove(0 .. n - (k-1)) // this greatly reduces the combinations checked
if has_next_combination(markers, pair_array):
next_greatest_combination(markers, pair_array) // pick new markers, in a reverse-binary counting fashion (most significant bit first way)
else:
print(best_sum)
break
One small trick I can think if you try to find lets say 3 indexes, is instead of iterating for the 3 indexes you can calculate the 3rd index when you know the first two indexes. For example when you know that
p1 = 1, p2 = 7 => p3 = 20 - (p1 + p2) = 12
This can be generalized when having N indexes the last one can always be inferred from the N-1 previous indexes.
I tried this in Python:
Index = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
Value = [17, 12, 5, 22, 3, 12, 6, 13, 7, 0, 2, 15 ]
maxSum = 0 SumInd = 20
for p1 in range(1,len(Index)+1):
for p2 in range(p1,len(Index)+1):
if (p1 + p2 < SumInd) and (p1 != p2):
p3 = SumInd - (p1 + p2) #If you know p1 and p2 calculate p3 index
if (p3 < len(Index)+1) and (p2 != p3) and (p1 != p3):
fooSum = Value[p1-1]+Value[p2-1] + Value[p3-1]
print(p1,p2,p3 , "Sum is ",fooSum)
if maxSum < fooSum:
maxSum = fooSum
print("Max Sum is ", maxSum)
Of course you need to save the indexes when you find maxSum. Also this implementation calculate many similar pairs (e.g. [1,9,10] and [9,10,1]). Perhaps a better solution could eliminate this pairs.
EDIT: Big Improvement I found a way to eliminate most unnecessary checks. Let's say you need 3 indexes. The first one checks the whole range of possible values. Let's say it is index1.
The other two indexes must sum at 20 - ind1 let's call this rest. The list of indexes is always ordered so you can have a back index showing the smallest value(first item in the list bigger than index1) and a front index that show the biggest values (last item in the list). So index2 = backIndex , index3 = frontIndex.
If the rest is smaller than the sum of index2,3 you could increase the back index (get the next bigger value) or if it is larger you decrease the front index until the two indexes meet each other where you break and increase index1. This eliminates checking (1,7,12) and (1,12,7) two times.
The code is here in Python:
maxSum = 0
SumInd = 20
for index_1 in range(1,len(Index)):
rest = SumInd - index_1
backIndex = index_1+1
frontIndex = len(Index)
while backIndex < frontIndex:
if rest > (backIndex + frontIndex):
backIndex = backIndex + 1
elif rest < (backIndex + frontIndex):
frontIndex = frontIndex - 1
else:
fooSum = Value[index_1-1]+Value[backIndex-1] + Value[frontIndex-1]
print("Checking for ",index_1,backIndex,frontIndex,' Sum of values:',fooSum)
if maxSum < fooSum:
indList = [index_1-1,backIndex,frontIndex]
maxSum = fooSum
backIndex = backIndex + 1 #To avoid Inf loop
print("Max Sum is ", maxSum,"at",indList)
and gives these results:
Checking for 1 7 12 Sum of values: 38
Checking for 1 8 11 Sum of values: 32
Checking for 1 9 10 Sum of values: 24
Checking for 2 6 12 Sum of values: 39
Checking for 2 7 11 Sum of values: 20
Checking for 2 8 10 Sum of values: 25
Checking for 3 5 12 Sum of values: 23
Checking for 3 6 11 Sum of values: 19
Checking for 3 7 10 Sum of values: 11
Checking for 3 8 9 Sum of values: 25
Checking for 4 5 11 Sum of values: 27
Checking for 4 6 10 Sum of values: 34
Checking for 4 7 9 Sum of values: 35
Checking for 5 6 9 Sum of values: 22
Checking for 5 7 8 Sum of values: 22
Max Sum is 39 at [1, 6, 12]
This can always be generalized for N indexes. The first N-2 indexes can search the whole range of the list (like index 1 in the case above, also it should be noted that all these indexes start checking from previous index value plus one until the end of the list to eliminate many duplicate checks).
The last two indexes can be calculated like I showed in my code and avoid many duplicate checks.
Here is my input data with four columns with space as the delimiter. I want to add the second and third column and print the result
sachin 200 10 2
sachin 900 20 2
sachin 500 30 3
Raju 400 40 4
Mike 100 50 5
Raju 50 60 6
My code is in the mid way
from pyspark import SparkContext
sc = SparkContext()
def getLineInfo(lines):
spLine = lines.split(' ')
name = str(spLine[0])
cash = int(spLine[1])
cash2 = int(spLine[2])
cash3 = int(spLine[3])
return (name,cash,cash2)
myFile = sc.textFile("D:\PYSK\cash.txt")
rdd = myFile.map(getLineInfo)
print rdd.collect()
From here I got the result as
[('sachin', 200, 10), ('sachin', 900, 20), ('sachin', 500, 30), ('Raju', 400, 40
), ('Mike', 100, 50), ('Raju', 50, 60)]
Now the final result I need is as below, adding the 2nd and 3rd column and display the remaining fields
sachin 210 2
sachin 920 2
sachin 530 3
Raju 440 4
Mike 150 5
Raju 110 6
Use this:
def getLineInfo(lines):
spLine = lines.split(' ')
name = str(spLine[0])
cash = int(spLine[1])
cash2 = int(spLine[2])
cash3 = int(spLine[3])
return (name, cash + cash2, cash3)
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am stuck at billions. The error is:
expected: "one billion two hundred thirty four million five hundred sixty seven thousand eight hundred ninety"
got: "one billion two hundred thirty four million " (using ==)
here is my code:
class Fixnum
def in_words
less_than_13={0 => 'zero', 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five', 6 => 'six', 7=> 'seven', 8 => 'eight', 9 => 'nine', 10 => 'ten', 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen'}
tens={20 => 'twenty', 30 => 'thirty', 40 => 'forty', 50 => 'fifty', 60 => 'sixty', 70 => 'seventy', 80 => 'eighty', 90 => 'ninety'}
case self
when 0..13
return less_than_13[self]
when 14, 16, 17, 19
return teenify
when 15
return 'fifteen'
when 18
return 'eighteen'
when 20, 30, 40, 50 , 60, 70, 80, 90
return tens[self]
when (20..99)
# tens = (self / 10) * 10
# tens = (77 / 10) * 10
# tens = (7) * 10
# tens = 70
tens = (self / 10) * 10
# ones = self - tens
# ones = 77 - 70
# ones = 7
ones = self - tens
return "#{tens.in_words} #{ones.in_words}"
when (100..999)
# 100
hundreds = self / 100
rest = self - (hundreds * 100)
if rest > 0
return "#{hundreds.in_words} hundred #{rest.in_words}"
else
return "#{hundreds.in_words} hundred"
end
when (999..99999)
thousend = self / 1000
rest = self - (thousend * 1000)
if rest > 0
return "#{thousend.in_words} thousand #{rest.in_words}"
else
return "#{thousend.in_words} thousand"
end
when (10000001..999999999)
million = self / 1000000
rest = self - (million * 1000000)
if rest > 0
return "#{million.in_words} million #{rest.in_words}"
else
return "#{million.in_words} million"
end
when (1234567890..999999999999)
billion = self / 1000000000
rest = self - (billion * 1000000000)
if rest > 0
return "#{billion.in_words} billion #{rest.in_words}"
else
return "#{billion.in_words} billion"
end
end
end
def teenify
return (self - 10).in_words + 'teen'
end
end
You have some big gaps in your number ranges. Look at them and see which one the number 567,890 would fall into. Answer: None of them. And for that matter, neither would 1,000,000 or 1,000,000,000. It skips right from 99,999 to 10,000,001, and then from 999,999,999 to 1,234,567,890.
Take a peak at your ranges, They seem to be all over the place after 10,000. I would suggest putting powers so you can see what ranges you expect easier. for example Millions range is (10000001..999999999) and should be
(10**6...10**9)