Error handling for SimpleDateFormat in Java - performance

I am writing a program that takes a users input for hours and minutes in the format HH:MM, and returns a string of that input. For example, 13:56 would be "four minutes to two".
I have created the code to do exactly that - take the input in that format and return a value as above. My issue is that I am not sure how to handle errors. I have a while loop that is meant to catch errors but it doesn't. I mainly want to ensure that if the user enters a character input (ee:rb or 12:bb etc.) or an invalid time (14:68 (I am going on a 12 hour clock)), that the program says "Error!" and makes the user try again.
I have worked with exception handling, but have not done so for SimpleDateFormat and I can't figure out why the below does not work.

Try this:
public static void main(String[] args) {
boolean safetyNet = false;
Scanner in = new Scanner(System.in);
Date d = new Date();
SimpleDateFormat simpFormat = new SimpleDateFormat("hh:mm");
while (!safetyNet) {
System.out.println("Please enter the time in hours and minutes: ");
String timeToString = in.next();
try {
d = simpFormat.parse(timeToString);
safetyNet = true;
String sHours = timeToString.substring(0, 2);
String sMinutes = timeToString.substring(3);
int hours = Integer.parseInt(sHours);
int minutes = Integer.parseInt(sMinutes);
String time=getTimeName(hours, minutes);
if(time.isEmpty()){
safetyNet = false;
}else{
System.out.printf("Time is: " + getTimeName(hours, minutes));
}
} catch (ParseException e) {
System.out.println("Error! Try again: ");
// e.printStackTrace();
}
}
in.close();
}
public static String getTimeName(int hours, int minutes) {
String timeName = "";
if (hours >= 1 && hours <= 12 && minutes >= 0 && minutes <= 59) {
String hourBank[] = { "", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten",
"Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen",
"Nineteen", "Twenty", "Twenty one", "Twenty two", "Twenty three", "Twenty four", "Twenty five",
"Twenty six", "Twenty seven", "Twenty eight", "Twenty nine" };
if (minutes == 0) {
timeName = hourBank[hours] + " O'clock";
}
else if (minutes == 15) {
timeName = "A quarter past " + hourBank[hours];
}
else if (minutes == 30) {
timeName = "Half Past " + hourBank[hours];
}
else if (hours == 12 && minutes == 45) {
timeName = "A quarter to " + hourBank[hours - 11];
}
else if (minutes == 45) {
timeName = "A quarter to " + hourBank[hours + 1];
}
else if (minutes <= 29) {
timeName = hourBank[minutes] + " minutes past " + hourBank[hours];
}
else if (hours == 12 && minutes >= 31 && minutes <= 59) {
timeName = hourBank[60 - minutes] + " minutes to " + hourBank[hours - 11];
}
else if (minutes >= 31 && minutes <= 60) {
timeName = hourBank[60 - minutes] + " minutes to " + hourBank[hours + 1];
} else {
timeName = "That's not the correct format!";
}
}else{
System.out.println("minutes are between 0 and 60 and hours are between 0 and 12");
}
return timeName;
}

Given that you are just expecting a simple string hh:mm, I might use String#matches here:
do {
timeToString = in.nextLine();
} while (!timeToString.matches("(1[0-2]|0[1-9]):[0-5]\\d"));
This above loop will iterate until the users enters a valid 12 hour hour:minute string. If you don't like this approach, another approach would be to use SimpleDateFormat#parse to attempt to parse the input. This method throws a ParseException, so you could try catching and looping on that.

Related

Creating List<Object> inside map

I have string like:
String input = "1 2 20\n"
+ "1 3 50\n"
+ "1 4 40\n"
+ "1 5 30\n"
+ "2 3 20\n"
+ "2 4 40\n"
+ "2 5 30\n"
+ "3 4 50\n"
+ "3 5 60\n"
+ "4 5 70\n";
}
My Nodes Class:
class Nodes{
Integer from;
Integer to;
Integer cost;
}
Corresponding to each String input i want a Nodes object.
SO far I have been able to do like:
List<Nodes> collect = new ArrayList<>();
for loop starts here until the inputs are exhausted.
String[] s = Arrays.stream("1 3 50".split(" ")).toArray(String[]::new);
Nodes nodes = new Nodes(Integer.valueOf(s[0]),Integer.valueOf(s[1]),Integer.valueOf(s[2]));
collect.add(nodes);
for loop ends here
Required output :
List<Nodes>
Is there a way so that I can create a List of Nodes inside stream only like map(h->new Nodes(h[0],h[1],h[2]))and at last collect it using Collectors.toList() so that i have List<Nodes>.
Try this one
List<Nodes> nodes = Arrays.stream(input.split("\\n"))
.map(s->s.split("\\s"))
.map(arr->new Nodes(Integer.valueOf(arr[0]),Integer.valueOf(arr[1]),
Integer.valueOf(arr[2])))
.collect(Collectors.toList());
I would make some modifications to your Nodes class first. Including some error handling in case there is something else than ints in your String. Then stream and collect:
import java.util.List;
import java.util.stream.Collectors;
public class StackOverflowTest {
public static void main(String[] args) {
String input = "1 2 20\n"
+ "1 3 50\n"
+ "1 4 40\n"
+ "1 5 30\n"
+ "2 3 20\n"
+ "2 4 40\n"
+ "2 5 30\n"
+ "3 4 50\n"
+ "3 5 60\n"
+ "4 5 70\n";
List<Nodes> list =
input.lines() // streaming each line
.map(s -> new Nodes(s.split(" "))) // creating Nodes
.collect(Collectors.toList()); // Collecting to List
System.out.println(list);
}
}
class Nodes{
Integer from;
Integer to;
Integer cost;
Nodes(String[] strings) {
this(stringToInts(strings)); // avoid throwing error in constructor
}
Nodes(int[] ints) {
this.from = ints[0];
this.to = ints[1];
this.cost = ints[2];
}
public String toString() {
return "Nodes:from=" + from + ".to=" + to + ".cost=" + cost + "\n";
}
private static int[] stringToInts(String[] strings) {
if (strings.length != 3) throw new AssertionError("String array of wrong size. Must be 3");
int[] ints = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
ints[i] = Integer.parseInt(strings[i]);
}
return ints;
}
}
On reflection the exeption handling can also be achieved just by adding
.map(arr-> {if (arr.length != 3) throw new AssertionError("Array size != 3"); return arr;})
to the Answer by Hadi J
I don't code java but in python there's a function called list() that converts string to lists and maybe there is one on java too.
or maybe use split(", ") and maybe it will work.

Generate maximum HH:MM from a list of 4 integers [duplicate]

This question already has answers here:
Find maximum possible time HH:MM by permuting four given digits
(25 answers)
Closed 5 years ago.
Note: Another question is the duplicate of this one. If I posted this question 6 months earlier than that one, then how can mine be a duplicate?
I have 4 non-negative integers a,b,c,d. All of them are less than or equal to 9. I have to return the maximum time that can be shown on the clock in 24-hour format.
For example: a=9, b=4, c=3, d=1, would yield 19:43
I have so far only been able to come up with brute-force approach which kind of tests all 24-possible combinations. Although this isn't too bad, I was wondering if there are more elegant approaches. All ideas better than brute force are welcome.
Note: It is not a homework question. I got this from an interview prep site but has no solutions there.
Generating all 24 permutations would work, but you don't have to do that. Your validation for the brute force method would require you to validate each digit, and you may as well build up the permutation as you validate each digit. Start with big numbers.
sort numbers in high -> low
iterate over each digit [i] and search through the list until you find the highest number that fits the requirements.
[0] must be <=2
[1] must be <=3 if [0]==2
[2] must be <=5
[3] can be anything
Remove that number from the list, and place it in position [i]
repeat for each digit
Each of those conditions could be expressed as lambda function in a list, making it easy to separate the search loop from the conditions.
The key is to sort the data and then apply these simple rules:
At least one element has to be <= 2
A second element has to be <= 5
If there are only two elements meeting the first two rules then one of them must be < 2
If the element selected for the first value is 2 then the element selected for the second value must be less than 4
The rules are easy to implement by using three counters:
less_than_3 - this must always be at least 1
less_than_6 - this must always be at least 2
less_than_4 - if a == 2 then less_than_4 must be at least 2
Here's a solution in JavaScript that could be further refactored.
function find_the_time(data) {
var arr = data.slice(), ans = {};
var count_less_than_three = 0, count_less_than_four = 0, count_less_than_six = 0;
console.log(arr);
arr.sort(function(a,b) { return a - b; });
if ((arr[0] > 2) || (arr[1] > 5)) {
// Rule 1 - Hh:mm must be <= 2
// Rule 2 - hh:Mm must be <= 5
console.log('No solution');
return -1;
}
for (var el of arr) {
if (el < 3) {
// count_less_than_three will be at least 1
count_less_than_three++;
}
if (el < 4) {
// count_less_than_four will be at least 1
count_less_than_four++;
}
if (el < 6) {
// count_less_than_six will be at least 2
count_less_than_six++;
}
}
if (count_less_than_three === count_less_than_six) {
if (count_less_than_three == 2) {
// Two elements have values less than 3
// so the time must be earlier than 20:00
// Rule 3 - Hh:mm must be <= 1
if (arr[0] > 1) {
console.log('No solution');
return -1;
} else {
ans.c = arr.splice((count_less_than_three - 1), 1);
ans.a = arr.splice((count_less_than_three - 2), 1);
ans.b = arr.splice(1, 1);
ans.d = arr.splice(0, 1);
}
} else {
ans.a = arr.splice((count_less_than_three - 1), 1);
ans.b = arr.splice((count_less_than_three - 2), 1);
if (arr[1] < 6) {
ans.c = arr.splice(1, 1);
ans.d = arr.splice(0, 1);
} else {
ans.d = arr.splice(1, 1);
ans.c = arr.splice(0, 1);
}
}
} else {
ans.a = arr.splice((count_less_than_three - 1), 1);
if (ans.a < 2) {
// b can have any value so select the largest available
ans.b = arr.splice(2, 1);
} else {
// a == 2 so count_less_than_four comes into play
// Rule 4 - hH:mm must be <= 3
// Array size has been reduced so decrement count_less_than_four
count_less_than_four--;
ans.b = arr.splice((count_less_than_four - 1), 1);
}
if (arr[1] < 6) {
ans.c = arr.splice(1, 1);
ans.d = arr.splice(0, 1);
} else {
ans.d = arr.splice(1, 1);
ans.c = arr.splice(0, 1);
}
}
console.log('Answer: ' + ans.a + '' + ans.b + ':' + ans.c + '' + ans.d);
return ans.a + '' + ans.b + ':' + ans.c + '' + ans.d;
}
var test_data = [
[ 2, 1, 2, 1 ],
[ 9, 5, 7, 1 ],
[ 2, 2, 7, 6 ],
[ 2, 6, 6, 1 ],
[ 0, 5, 9, 8 ],
[ 0, 6, 9, 8 ],
[ 2, 5, 9, 3 ]
];
test_data.forEach(find_the_time);
You can change time to minutes.
Then you can compare it.
//23:59 ==> 23*60+59 ==1439 min
//(10a+b)*60+(10c+d)<=1439
This is my code.
String function(int[] numbers){
int num[] = numbers;
int temp = 0;
int cnt=0;
int numA=0;
int numB=0;
int numC=0;
int numD=0;
for(int a=0;a<num.length; a++){
for(int b=0;b<num.length; b++){
for(int c=0;c<num.length; c++){
for(int d=0;d<num.length; d++){
if(a!=b && a!=c && a!=d
&& b!=c && b!=d
&& c!=d){
if((10*num[c]+num[d])<60) {
int cal = (10 * num[a] + num[b]) * 60 + (10 * num[c] + num[d]);
Log.d("Joon1979", "Input Numbers [ " + num[a] + ", " + num[b] + ", " + num[c] + ", " + num[d] + " ]");
if (cal <= 1439) {
cnt++;
if (temp < cal) {
temp = cal;
numA = num[a];
numB = num[b];
numC = num[c];
numD = num[d];
}
}
}
}
}
}
}
}
if(cnt==0){
return "impossible";
}else {
return numA+""+numB+" : "+numC+""+numD;
}
}

Determine day based on number

I just want to ask if how do you determine
Enter a number: 14
Then the date to day is Sunday.
the above demonstration is from 1-7=monday-sunday then if the value is 8 then its monday again...but how could I determine it?using loops and modulo?...
I appreciate any comments for helping me...
any language are ok, I just want to know the algorithm with it...
You can just use module
Module got to 0 so it would be something like
<?php
$value = 13;
$daynames = array("mon", "tues", "wed", "thur", "fri", "sat", "sun");
// The + 1 is because % is 0, and you want 1-7
echo (($value % 7) + 1) . "day of the week";
echo "the day is " . $daynames[($value % 7)];
?>
Example: http://codepad.org/wbGuMI06
If you have a switch/case or if/else for the seven days you can use modulo 7 to get the input into the desired range of 7 days.
You can use a switch statement and modulo arithmetic to do this.
The first step to learning computer science is to learn that numbers don't usually start at 1. They start at 0. Getting this idea down will help you tremendously in the future!
// accept numbers 0-6. If 7 were to get put in, it would end up being 0 since 7 % 7 = 0.
switch(num % 7) {
case 0: return "Sunday";
case 1: return "Monday";
case 2: return "Tuesday";
/// rest here...
default: throw new IllegalArgumentException();
}
Taking the number modulo 7 would seem like the obvious possibility.
In C++, int day = (i-1) % 7; will give you a zero-based offset. Here's sample code:
#include <iostream>
#include<string>
using namespace std;
int main()
{
static const std::string days [] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
static const size_t num_days = sizeof(days)/sizeof(days[0]);
for( int i = 1; i <= 31; ++i )
{
int day = (i-1) % 7;
cout << day << " = " << days[day] << "\n";
}
}
Get modulo 7 of the int value thats passed in and make a switch statement for it.
switch:
case 1:
Sunday
case 2:
Monday
// and so on
string day;
int inputNumber;
if(inputNumber%7 == 0)
day = "monday"; // or sunday if you prefer :p
else if(inputNumber%7 == 1)
day = tuesday
...
...
...
datArr= new Array ('Sun', 'Mon', 'Tue',Wen', 'Thu, 'Fri', 'Sat');
day =datArr[(daynum%7)];
If Sunday gets treated as day zero there is no need to subtract 1 after the modulo. Of course most of the solutions will fail with zero dive if an actual value of zero is encountered.
import java.util.Scanner;
public class TestMain {
private static final String[] DAYS = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thusday", "Friday", "Saturday" };
public static void main(final String[] args) {
System.out.print("Enter a number: ");
final Scanner scanner = new Scanner(System.in);
final int n = scanner.nextInt();
System.out.print("Then the date to day is " + DAYS[n % 7]);
}
}

Algorithm that converts numeric amount into English words

What is the most efficient way to convert numeric amount into English words
e.g. 12 to twelve
127 to one hundred twenty-seven
That didn't take long. This is an implementation written in Java.
http://snippets.dzone.com/posts/show/3685
Code
public class IntToEnglish {
static String[] to_19 = { "zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
static String[] tens = { "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
static String[] denom = { "",
"thousand", "million", "billion", "trillion", "quadrillion",
"quintillion", "sextillion", "septillion", "octillion", "nonillion",
"decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
"sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion" };
public static void main(String[] argv) throws Exception {
int tstValue = Integer.parseInt(argv[0]);
IntToEnglish itoe = new IntToEnglish();
System.out.println(itoe.english_number(tstValue));
/* for (int i = 0; i < 2147483647; i++) {
System.out.println(itoe.english_number(i));
} */
}
// convert a value < 100 to English.
private String convert_nn(int val) throws Exception {
if (val < 20)
return to_19[val];
for (int v = 0; v < tens.length; v++) {
String dcap = tens[v];
int dval = 20 + 10 * v;
if (dval + 10 > val) {
if ((val % 10) != 0)
return dcap + "-" + to_19[val % 10];
return dcap;
}
}
throw new Exception("Should never get here, less than 100 failure");
}
// convert a value < 1000 to english, special cased because it is the level that kicks
// off the < 100 special case. The rest are more general. This also allows you to
// get strings in the form of "forty-five hundred" if called directly.
private String convert_nnn(int val) throws Exception {
String word = "";
int rem = val / 100;
int mod = val % 100;
if (rem > 0) {
word = to_19[rem] + " hundred";
if (mod > 0) {
word = word + " ";
}
}
if (mod > 0) {
word = word + convert_nn(mod);
}
return word;
}
public String english_number(int val) throws Exception {
if (val < 100) {
return convert_nn(val);
}
if (val < 1000) {
return convert_nnn(val);
}
for (int v = 0; v < denom.length; v++) {
int didx = v - 1;
int dval = new Double(Math.pow(1000, v)).intValue();
if (dval > val) {
int mod = new Double(Math.pow(1000, didx)).intValue();
int l = val / mod;
int r = val - (l * mod);
String ret = convert_nnn(l) + " " + denom[didx];
if (r > 0) {
ret = ret + ", " + english_number(r);
}
return ret;
}
}
throw new Exception("Should never get here, bottomed out in english_number");
}
}
One way to accomplish this would be to use look up tables. It would be somewhat brute force, but easy to setup. For instance, you could have the words for 0-99 in one table, then a table for tens, hundreds, thousands, etc. Some simple math will give you the index of the word you need from each table.
This is some old python code on my hard drive. There might be bugs but it should show the basic idea:
class Translator:
def transformInt(self, x):
translateNumbers(0,[str(x)])
def threeDigitsNumber(self,number):
snumber=self.twoDigitsNumber(number/100)
if number/100!=0:
snumber+=" hundred "
snumber+self.twoDigitsNumber(number)
return snumber+self.twoDigitsNumber(number)
def twoDigitsNumber(self,number):
snumber=""
if number%100==10:
snumber+="ten"
elif number%100==11:
snumber+="eleven"
elif number%100==12:
snumber+="twelve"
elif number%100==13:
snumber+="thirteen"
elif number%100==14:
snumber+="fourteen"
elif number%100==15:
snumber+="fifteen"
elif number%100==16:
snumber+="sixteen"
elif number%100==17:
snumber+="seventeen"
elif number%100==18:
snumber+="eighteen"
elif number%100==19:
snumber+="nineteen"
else:
if (number%100)/10==2:
snumber+="twenty-"
elif (number%100)/10==3:
snumber+="thirty-"
elif (number%100)/10==4:
snumber+="forty-"
elif (number%100)/10==5:
snumber+="fifty-"
elif (number%100)/10==6:
snumber+="sixty-"
elif (number%100)/10==7:
snumber+="seventy-"
elif (number%100)/10==8:
snumber+="eighty-"
elif (number%100)/10==9:
snumber+="ninety-"
if (number%10)==1:
snumber+="one"
elif (number%10)==2:
snumber+="two"
elif (number%10)==3:
snumber+="three"
elif (number%10)==4:
snumber+="four"
elif (number%10)==5:
snumber+="five"
elif (number%10)==6:
snumber+="six"
elif (number%10)==7:
snumber+="seven"
elif (number%10)==8:
snumber+="eight"
elif (number%10)==9:
snumber+="nine"
elif (number%10)==0:
if snumber!="":
if snumber[len(snumber)-1]=="-":
snumber=snumber[0:len(snumber)-1]
return snumber
def translateNumbers(self,counter,words):
if counter+1<len(words):
self.translateNumbers(counter+1,words)
else:
if counter==len(words):
return True
k=0
while k<len(words[counter]):
if (not (ord(words[counter][k])>47 and ord(words[counter][k])<58)):
break
k+=1
if (k!=len(words[counter]) or k==0):
return 1
number=int(words[counter])
from copy import copy
if number==0:
self.translateNumbers(counter+1,copy(words[0:counter]+["zero"]+words[counter+1:len(words)]))
self.next.append(copy(words[0:counter]+["zero"]+words[counter+1:len(words)]))
return 1
if number<10000:
self.translateNumbers(counter+1,copy(words[0:counter]
+self.seperatewords(self.threeDigitsNumber(number))
+words[counter+1:len(words)]))
self.next.append(copy(words[0:counter]
+self.seperatewords(self.threeDigitsNumber(number))
+words[counter+1:len(words)]))
if number>999:
snumber=""
if number>1000000000:
snumber+=self.threeDigitsNumber(number/1000000000)+" billion "
number=number%1000000000
if number>1000000:
snumber+=self.threeDigitsNumber(number/1000000)+" million "
number=number%1000000
if number>1000:
snumber+=self.threeDigitsNumber(number/1000)+" thousand "
number=number%1000
snumber+=self.threeDigitsNumber(number)
self.translateNumbers(counter+1,copy(words[0:counter]+self.seperatewords(snumber)
+words[counter+1:len(words)]))
self.next.append(copy(words[0:counter]+self.seperatewords(snumber)
+words[counter+1:len(words)]))
This solution doesn't attempt to account for trailing spaces, but it is pretty fast.
typedef const char* cstring;
using std::string;
using std::endl;
std::ostream& GetOnes(std::ostream &output, int onesValue)
{
cstring ones[] = { "zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine" };
output << ones[onesValue];
return output;
}
std::ostream& GetSubMagnitude(std::ostream &output, int subMagnitude)
{
cstring tens[] = { "zeroty", "ten", "twenty", "thirty", "fourty", "fifty",
"sixty", "seventy", "eighty", "ninety"};
if (subMagnitude / 100 != 0)
{
GetOnes(output, subMagnitude / 100) << " hundred ";
GetSubMagnitude(output, subMagnitude - subMagnitude / 100 * 100);
}
else
{
if (subMagnitude >= 20)
{
output << tens[subMagnitude / 10] << " ";
GetOnes(output, subMagnitude - subMagnitude / 10 * 10);
}
else if (subMagnitude >= 10)
{
cstring teens[] = { "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen" };
output << teens[subMagnitude - 10] << " ";
}
else
{
GetOnes(output, subMagnitude) << " ";
}
}
return output;
}
std::ostream& GetLongNumber(std::ostream &output, double input)
{
cstring magnitudes[] = {"", "hundred", "thousand", "million", "billion",
"trillion"};
double magnitudeTests[] = {1, 100.0, 1000.0, 1000000.0, 1000000000.0,
1000000000000.0 };
int magTestIndex = 0;
while (floor(input / magnitudeTests[magTestIndex++]) != 0);
magTestIndex -= 2;
if (magTestIndex >= 0)
{
double subMagnitude = input / magnitudeTests[magTestIndex];
GetSubMagnitude(output, (int)subMagnitude);
if (magTestIndex) {
output << magnitudes[magTestIndex] << " ";
double remainder = input - (floor(input /
magnitudeTests[magTestIndex]) *
magnitudeTests[magTestIndex]);
if (floor(remainder) > 0)
{
GetLongNumber(output, remainder);
}
}
}
else
{
output << "zero";
}
return output;
}
Start by solving 1-99, using a list of numbers for 1-20, and then 30, 40, ..., 90. Then add hundreds to get 1-999. Then use that routine to give the number of each power of 1,000 for as high as you want to go (I think the highest standard nomenclature is for decillion, which is 10^33).
One slight caveat is that it's a little tricky to get the blanks right in all cases if you're trying to start and end without an excess blank. The easy solution is to put a blank after every word, and then strip off the trailing blank when you're all done. If you try to be more precise while building the string, you're likely to end up with missing blanks or excess blanks.
.) make a library of all numbers & positions (e.g. 1 has other notation than 10, another than 100 etc)
.) make a list of exceptions (e.g. for 12) and be aware, that in your algorythm, the same exception are for 112, 1012 etc.
if you want even more speed, make a cached set of numbers that you need.
Note some rules:
Tens numbers (twenty, thirty, etc.) ending in y are followed by hyphens.
Teens are special (except 15-19, but they're still special).
Everything else is just some combination of digit place like "three thousand".
You can get the place of a number by using floor division of integers: 532 / 100 -> 5
This is part of Common Lisp!
Here's how GNU CLISP does it, and here's how CMUCL does it (easier to read, IMHO).
Doing a code search for "format million billion" will turn up lots of them.

Making human readable representations of an Integer

Here's a coding problem for those that like this kind of thing. Let's see your implementations (in your language of choice, of course) of a function which returns a human readable String representation of a specified Integer. For example:
humanReadable(1) returns "one".
humanReadable(53) returns "fifty-three".
humanReadable(723603) returns "seven hundred and twenty-three thousand, six hundred and three".
humanReadable(1456376562) returns "one billion, four hundred and fifty-six million, three hundred and seventy-six thousand, five hundred and sixty-two".
Bonus points for particularly clever/elegant solutions!
It might seem like a pointless exercise, but there are number of real world applications for this kind of algorithm (although supporting numbers as high as a billion may be overkill :-)
There was already a question about this:
Convert integers to written numbers
The answer is for C#, but I think you can figure it out.
import math
def encodeOnesDigit(num):
return ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'][num]
def encodeTensDigit(num):
return ['twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'][num-2]
def encodeTeens(num):
if num < 10:
return encodeOnesDigit(num)
else:
return ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'][num-10]
def encodeTriplet(num):
if num == 0: return ''
str = ''
if num >= 100:
str = encodeOnesDigit(num / 100) + ' hundred'
tens = num % 100
if tens >= 20:
if str != '': str += ' '
str += encodeTensDigit(tens / 10)
if tens % 10 > 0:
str += '-' + encodeOnesDigit(tens % 10)
elif tens != 0:
if str != '': str += ' '
str += encodeTeens(tens)
return str
def zipNumbers(numList):
if len(numList) == 1:
return numList[0]
strList = ['', ' thousand', ' million', ' billion'] # Add more as needed
strList = strList[:len(numList)]
strList.reverse()
joinedList = zip(numList, strList)
joinedList = [item for item in joinedList if item[0] != '']
return ', '.join(''.join(item) for item in joinedList)
def humanReadable(num):
if num == 0: return 'zero'
negative = False
if num < 0:
num *= -1
negative = True
numString = str(num)
tripletCount = int(math.ceil(len(numString) / 3.0))
numString = numString.zfill(tripletCount * 3)
tripletList = [int(numString[i*3:i*3+3]) for i in range(tripletCount)]
readableList = [encodeTriplet(num) for num in tripletList]
readableStr = zipNumbers(readableList)
return 'negative ' + readableStr if negative else readableStr
Supports up to 999 million, but no negative numbers:
String humanReadable(int inputNumber) {
if (inputNumber == -1) {
return "";
}
int remainder;
int quotient;
quotient = inputNumber / 1000000;
remainder = inputNumber % 1000000;
if (quotient > 0) {
return humanReadable(quotient) + " million, " + humanReadable(remainder);
}
quotient = inputNumber / 1000;
remainder = inputNumber % 1000;
if (quotient > 0) {
return humanReadable(quotient) + " thousand, " + humanReadable(remainder);
}
quotient = inputNumber / 100;
remainder = inputNumber % 100;
if (quotient > 0) {
return humanReadable(quotient) + " hundred, " + humanReadable(remainder);
}
quotient = inputNumber / 10;
remainder = inputNumber % 10;
if (remainder == 0) {
//hackish way to flag the algorithm to not output something like "twenty zero"
remainder = -1;
}
if (quotient == 1) {
switch(inputNumber) {
case 10:
return "ten";
case 11:
return "eleven";
case 12:
return "twelve";
case 13:
return "thirteen";
case 14:
return "fourteen";
case 15:
return "fifteen";
case 16:
return "sixteen";
case 17:
return "seventeen";
case 18:
return "eighteen";
case 19:
return "nineteen";
}
}
switch(quotient) {
case 2:
return "twenty " + humanReadable(remainder);
case 3:
return "thirty " + humanReadable(remainder);
case 4:
return "forty " + humanReadable(remainder);
case 5:
return "fifty " + humanReadable(remainder);
case 6:
return "sixty " + humanReadable(remainder);
case 7:
return "seventy " + humanReadable(remainder);
case 8:
return "eighty " + humanReadable(remainder);
case 9:
return "ninety " + humanReadable(remainder);
}
switch(inputNumber) {
case 0:
return "zero";
case 1:
return "one";
case 2:
return "two";
case 3:
return "three";
case 4:
return "four";
case 5:
return "five";
case 6:
return "six";
case 7:
return "seven";
case 8:
return "eight";
case 9:
return "nine";
}
}
using System;
namespace HumanReadable
{
public static class HumanReadableExt
{
private static readonly string[] _digits = {
"", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "eleven", "twelve",
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen"
};
private static readonly string[] _teens = {
"", "", "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety"
};
private static readonly string[] _illions = {
"", "thousand", "million", "billion", "trillion"
};
private static string Seg(int number)
{
var work = string.Empty;
if (number >= 100)
work += _digits[number / 100] + " hundred ";
if ((number % 100) < 20)
work += _digits[number % 100];
else
work += _teens[(number % 100) / 10] + "-" + _digits[number % 10];
return work;
}
public static string HumanReadable(this int number)
{
if (number == 0)
return "zero";
var work = string.Empty;
var parts = new string[_illions.Length];
for (var ind = 0; ind < parts.Length; ind++)
parts[ind] = Seg((int) (number % Math.Pow(1000, ind + 1) / Math.Pow(1000, ind)));
for (var ind = 0; ind < parts.Length; ind++)
if (!string.IsNullOrEmpty(parts[ind]))
work = parts[ind] + " " + _illions[ind] + ", " + work;
work = work.TrimEnd(',', ' ');
var lastSpace = work.LastIndexOf(' ');
if (lastSpace >= 0)
work = work.Substring(0, lastSpace) + " and" + work.Substring(lastSpace);
return work;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(1.HumanReadable());
Console.WriteLine(53.HumanReadable());
Console.WriteLine(723603.HumanReadable());
Console.WriteLine(1456376562.HumanReadable());
Console.ReadLine();
}
}
}
There's one huge problem about this function implementation. It is it's future localization. That function, written by english native speaker, most probably wouldn't work right for any other language than english. It is nearly impossible to write general easy localizable function for any human language dialect in a world, unless you really need to keep it general. Actually in real world you do not need to operate with huge integer numbers, so you can just keep all the numbers in a big (or even not so big) string array.
agreed that there are a number of real world applications.
as such there's already a number of real world implementations.
it's been part of bsdgames since pretty much forever...
> man number

Resources