Get the IBAN number from an emv card - emv

i have some issues with reading the IBAN number from the german CashCards (also known as Geldkarte).
I can communicate with my card, and i get some informations from it. but i don`t know which commandApdu i must send to the card, to get the IBAN number...
The application runs on Java 7 and i use the java.smartcardio api
Protocoll is T=1
my commandApdu to get the date looks like this:
byte[] commandBytes = new byte[]{0x00, (byte)0xa4, 0x04, 0x00, 0x07, (byte)0xa0, 0x00, 0x00, 0x00,0x04, 0x30, 0x60, 0x00};
the information i get is:
6F 32 84 07 A0 00 00 00 04 30 60 A5 27 50 07 4D 61 65 73 74 72 6F 87 01 03 9F 38 09 9F 33 02 9F 35 01 9F 40 01 5F 2D 04 64 65 65 6E BF 0C 05 9F 4D 02 19 0A
Can anyone tell me the correct apdu for getting the IBAN number?
i am sorry if i forgott some information needed, but this is my first question in this board :-)

Okay so the card has sent back this:
6F328407A0000000043060A52750074D61657374726F8701039F38099F33029F35019F40015F2D046465656EBF0C059F4D02190A
Which translates to:
6F File Control Information (FCI) Template
84 Dedicated File (DF) Name
A0000000043060
A5 File Control Information (FCI) Proprietary Template
50 Application Label
M a e s t r o
87 Application Priority Indicator
03
9F38 Processing Options Data Object List (PDOL)
9F33029F35019F4001
5F2D Language Preference
d e e n
BF0C File Control Information (FCI) Issuer Discretionary Data
9F4D Log Entry
190A
So now you've selected the application you'll want to send a series of 'Read Record' commands to it to get the data out of it like (Card number, expiry date, card holder name, IBAN (if it's in there, haven't seen it before)). The structure of the 'Read Record' command can be found in EMV Book 3 however here's some rough psuedocode as to what your Read Record loop should look like. Off the top of my head I usually set NUM_SFIS to 5 and NUM_RECORDS to 16 as there's not usually anything past these points.
for (int sfiNum = 1; sfiNum <= NUM_SFIS; sfiNum++)
{
for (int rec = 1; rec <= NUM_RECORDS; rec++)
{
byte[] response = tag.transceive(new byte[]{0x00,(byte)0xB2 (byte)rec, (byte)((byte)(sfiNum << 3) | 4), 0x00});
}
}

i solved my problem after a long time this way:
At first send a command to the card, to select the aid (application identifier):
private static byte[] aidWithPossibleIban = new byte[] { 0x00, (byte) 0xa4,
0x04, 0x00, 0x09, (byte) 0xa0, 0x00, 0x00, 0x00, 0x59, 0x45, 0x43,
0x01, 0x00, 0x00 };
then i hat to raise the security-level:
private static byte[] cmdRaiseSecurityLevel = new byte[] { 0x00, 0x22,
(byte) 0xf3, 0x02 };
last thing to do was to read the record:
private static byte[] readSelectedRecord = new byte[] { 0x00, (byte) 0xb2,
0x01, (byte) 0xa4, 0x00 };
regards
Andreas

I would like to add, the IBAN returning from the card is not straightforward.
The IBAN returned is that of the main Bank, and then the account number from the card holder in other record. Therefore one must come out with the right IBAN through code as the check digit has to be calculated as seen here
Since in records we find Country Code (DE), Bankleitzahl BLZ (8 Digits) and Account Number (10 digits), Check Digit can be calculated through
public string ReturnIBAN(string lkz, string blz, string kntnr, bool groupedReturn = true)
{
string bban = string.Empty;
lkz = lkz.ToUpper();
switch (lkz)
{
case "AT":
{
bban = blz.PadLeft(5, '0') + kntnr.PadLeft(11, '0');
}
break;
case "DE":
{
bban = blz.PadLeft(8, '0') + kntnr.PadLeft(10, '0');
}
break;
case "CH":
{
bban = blz.PadLeft(5, '0') + kntnr.PadLeft(12, '0');
}
break;
}
string sum = bban + lkz.Aggregate("", (current, c) => current + (c - 55).ToString()) + "00";
var d = decimal.Parse(sum);
var checksum = 98 - (d % 97);
string iban = lkz + checksum.ToString().PadLeft(2, '0') + bban;
return groupedReturn ? iban.Select((c, i) => (i % 4 == 3) ? c + " " : c + "").Aggregate("", (current, c) => current + c) : iban;
}
Source (In German): here

Related

Accurate JSON text encoding detection

In RFC4627 a method for identifying the Unicode encoding when a BOM is not present was described. This relied on the first 2 characters in the JSON text to always be ASCII characters. But in RFC7159, the specification defines JSON text as "ws value ws"; implying that a single string value would also be valid. So the first character will be the opening quote, but then any Unicode character allowed in a string could follow. Considering that RFC7159 also discourages the use of a BOM; and no longer describes the procedure for detecting the encoding from the first 4 octets (bytes), how should one detect it? UTF-32 should still work correctly as described in RFC4627, because the first character is four bytes and should still be ASCII, but what about UTF-16? The second (2-byte) character might not contain a zero-byte to help identify the correct encoding.
Update
This answer has been written for JSON according RFC 7159 whose character encoding was allowed to use all unicode schemes (UTF-8, UTF-16, or UTF-32), where UTF-8 was the "default".
The current RFC 8259 restricts the character encoding to be only UTF-8, which is a reasonable constraint.
After taking a look at an implementation which I made a couple years ago, I can tell that it's possible to unambiguously detect the given Unicode Scheme from just one character, given the following assumptions:
The input must be Unicode
The first character must be ASCII
There must be no BOM
Consider this:
Assuming the first character is a "[" (0x5B) - an ASCII.
Then, we may get these byte patterns:
UTF_32LE: 5B 00 00 00
UTF_32BE: 00 00 00 5B
UTF_16LE: 5B 00 xx xx
UTF_16BE: 00 5B xx xx
UTF_8: 5B xx xx xx
where "xx" is either EOF or any other byte.
We should also note, that according RFC7159, the shortest valid JSON can be just one character. That is, it can be possibly 1, 2 or 4 byte - depending of the Unicode Scheme.
So, if it helps, here is an implementation in C++:
namespace json {
//
// Detect Encoding
//
// Tries to determine the Unicode encoding of the input starting at
// first. A BOM shall not be present (you might check with function
// json::unicode::detect_bom() whether there is a BOM, in which case
// you don't need to call this function when a BOM is present).
//
// Return values:
//
// json::unicode::UNICODE_ENCODING_UTF_8
// json::unicode::UNICODE_ENCODING_UTF_16LE
// json::unicode::UNICODE_ENCODING_UTF_16BE
// json::unicode::UNICODE_ENCODING_UTF_32LE
// json::unicode::UNICODE_ENCODING_UTF_32BE
//
// -1: unexpected EOF
// -2: unknown encoding
//
// Note:
// detect_encoding() requires to read ahead a few bytes in order to deter-
// mine the encoding. In case of InputIterators, this has the consequences
// that these iterators cannot be reused, for example for a parser.
// Usually, this requires to reset the istreambuff, that is using the
// member functions pubseekpos() or pupseekoff() in order to reset the get
// pointer of the stream buffer to its initial position.
// However, certain istreambuf implementations may not be able to set the
// stream pos at arbitrary positions. In this case, this method cannot be
// used and other edjucated guesses to determine the encoding may be
// needed.
template <typename Iterator>
inline int
detect_encoding(Iterator first, Iterator last)
{
// Assuming the input is Unicode!
// Assuming first character is ASCII!
// The first character must be an ASCII character, say a "[" (0x5B)
// UTF_32LE: 5B 00 00 00
// UTF_32BE: 00 00 00 5B
// UTF_16LE: 5B 00 xx xx
// UTF_16BE: 00 5B xx xx
// UTF_8: 5B xx xx xx
uint32_t c = 0xFFFFFF00;
while (first != last) {
uint32_t ascii;
if (static_cast<uint8_t>(*first) == 0)
ascii = 0; // zero byte
else if (static_cast<uint8_t>(*first) < 0x80)
ascii = 0x01; // ascii byte
else if (*first == EOF)
break;
else
ascii = 0x02; // non-ascii byte, that is a lead or trail byte
c = c << 8 | ascii;
switch (c) {
// reading first byte
case 0xFFFF0000: // first byte was 0
case 0xFFFF0001: // first byte was ASCII
++first;
continue;
case 0xFFFF0002:
return -2; // this is bogus
// reading second byte
case 0xFF000000: // 00 00
++first;
continue;
case 0xFF000001: // 00 01
return json::unicode::UNICODE_ENCODING_UTF_16BE;
case 0xFF000100: // 01 00
++first;
continue;
case 0xFF000101: // 01 01
return json::unicode::UNICODE_ENCODING_UTF_8;
// reading third byte:
case 0x00000000: // 00 00 00
case 0x00010000: // 01 00 00
++first;
continue;
//case 0x00000001: // 00 00 01 bogus
//case 0x00000100: // 00 01 00 na
//case 0x00000101: // 00 01 01 na
case 0x00010001: // 01 00 01
return json::unicode::UNICODE_ENCODING_UTF_16LE;
// reading fourth byte
case 0x01000000:
return json::unicode::UNICODE_ENCODING_UTF_32LE;
case 0x00000001:
return json::unicode::UNICODE_ENCODING_UTF_32BE;
default:
return -2; // could not determine encoding, that is,
// assuming the first byte is an ASCII.
} // switch
} // while
// premature EOF
return -1;
}
}

How to print a number in Assembly 8086?

I'm trying to write a function that receives a number (which I pushed earlier), and prints it. How can I do it?
What I have so far:
org 100h
push 10
call print_num
print_num:
push bp
mov bp, sp
mov ax, [bp+2*2]
mov bx, cs
mov es, bx
mov dx, string
mov di, dx
stosw
mov ah, 09h
int 21h
pop bp
ret
string:
What you're placing at the address of string is a numerical value, not the string representation of that value.
The value 12 and the string "12" are two separate things. Seen as a 16-bit hexadecimal value, 12 would be 0x000C while "12" would be 0x3231 (0x32 == '2', 0x31 == '1').
You need to convert the numerical value into its string representation and then print the resulting string.Rather than just pasting a finished solution I'll show a simple way of how this could be done in C, which should be enough for you to base an 8086 implementation on:
char string[8], *stringptr;
short num = 123;
string[7] = '$'; // DOS string terminator
// The string will be filled up backwards
stringptr = string + 6;
while (stringptr >= string) {
*stringptr = '0' + (num % 10); // '3' on the first iteration, '2' on the second, etc
num /= 10; // 123 => 12 => 1 => 0
if (num == 0) break;
stringptr--;
}

Code Golf: Conway's Game of Life

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The Challenge: Write the shortest program that implements John H. Conway's Game of Life cellular automaton. [link]
EDIT: After about a week of competition, I have selected a victor: pdehaan, for managing to beat the Matlab solution by one character with perl.
For those who haven't heard of Game of Life, you take a grid (ideally infinite) of square cells. Cells can be alive (filled) or dead (empty). We determine which cells are alive in the next step of time by applying the following rules:
Any live cell with fewer than two live neighbours dies, as if caused by under-population.
Any live cell with more than three live neighbours dies, as if by overcrowding.
Any live cell with two or three live neighbours lives on to the next generation.
Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
Your program will read in a 40x80 character ASCII text file specified as a command-line argument, as well as the number of iterations (N) to perform. Finally, it will output to an ASCII file out.txt the state of the system after N iterations.
Here is an example run with relevant files:
in.txt:
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
..................................XX............................................
..................................X.............................................
.......................................X........................................
................................XXXXXX.X........................................
................................X...............................................
.................................XX.XX...XX.....................................
..................................X.X....X.X....................................
..................................X.X......X....................................
...................................X.......XX...................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
Iterate 100 times:
Q:\>life in.txt 100
Resultant Output (out.txt)
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
..................................XX............................................
..................................X.X...........................................
....................................X...........................................
................................XXXXX.XX........................................
................................X.....X.........................................
.................................XX.XX...XX.....................................
..................................X.X....X.X....................................
..................................X.X......X....................................
...................................X.......XX...................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
The Rules:
You need to use file I/O to read/write the files.
You need to accept an input file and the number of iterations as arguments
You need to generate out.txt (overwrite if it exists) in the specified format
You don't need to deal with the edges of the board (wraparound, infinite grids .etc)
EDIT: You do need to have newlines in your output file.
The winner will be determined by character count.
Good luck!
Mathematica - 179 163 154 151 chars
a = {2, 2, 2};
s = Export["out.txt",
CellularAutomaton[{224, {2, {a, {2, 1, 2}, a}}, {1,1}},
(ReadList[#1, Byte, RecordLists → 2>1] - 46)/ 42, #2]〚#2〛
/. {0 → ".", 1 → "X"}, "Table"] &
Spaces added for readability
Invoke with
s["c:\life.txt", 100]
Animation:
You can also get a graph of the mean population over time:
A nice pattern for generating gliders from Wikipedia
AFAIK Mathematica uses a Cellular Automaton to generate random numbers using Rule 30.
MATLAB 7.8.0 (R2009a) - 174 171 161 150 138 131 128 124 characters
Function syntax: (124 characters)
Here's the easier-to-read version (with unnecessary newlines and whitespace added for better formatting):
function l(f,N),
b=char(importdata(f))>46;
for c=1:N,
b=~fix(filter2(ones(3),b)-b/2-3);
end;
dlmwrite('out.txt',char(b*42+46),'')
And here's how the program is run from the MATLAB Command Window:
l('in.txt',100)
Command syntax: (130 characters)
After a comment about calling functions with a command syntax, I dug a little deeper and found out that MATLAB functions can in fact be invoked with a command-line format (with some restrictions). You learn something new every day!
function l(f,N),
b=char(importdata(f))>46;
for c=1:eval(N),
b=~fix(filter2(ones(3),b)-b/2-3);
end;
dlmwrite('out.txt',char(b*42+46),'')
And here's how the program is run from the MATLAB Command Window:
l in.txt 100
Additional Challenge: Tweetable GIF maker - 136 characters
I thought for fun I'd see if I could dump the output to a GIF file instead of a text file, while still keeping the character count below 140 (i.e. "tweetable"). Here's the nicely-formatted code:
function l(f,N),
b=char(importdata(f))>46;
k=ones(3);
for c=1:N+1,
a(:,:,:,c)=kron(b,k);
b=~fix(filter2(k,b)-b/2-3);
end;
imwrite(~a,'out.gif')
Although IMWRITE is supposed to create a GIF that loops infinitely by default, my GIF is only looping once. Perhaps this is a bug that has been fixed in newer versions of MATLAB. So, to make the animation last longer and make the evolution steps easier to see, I left the frame delay at the default value (which seems to be around half a second). Here's the GIF output using the Gosper Glider Gun pattern:
Improvements
Update 1: Changed the matrix b from a logical (i.e. "boolean") type to a numerical one to get rid of a few conversions.
Update 2: Shortened the code for loading the file and used the function MAGIC as a trick to create the convolution kernel in fewer characters.
Update 3: Simplified the indexing logic, replaced ~~b+0 with b/42, and replaced 'same' with 's' as an argument to CONV2 (and it surprisingly still worked!).
Update 4: I guess I should have searched online first, since Loren from The MathWorks blogged about golfing and the Game of Life earlier this year. I incorporated some of the techniques discussed there, which required me to change b back to a logical matrix.
Update 5: A comment from Aslak Grinsted on the above mentioned blog post suggests an even shorter algorithm for both the logic and performing the convolution (using the function FILTER2), so I "incorporated" (read "copied") his suggestions. ;)
Update 6: Trimmed two characters from the initialization of b and reworked the logic in the loop to save 1 additional character.
Update 7: Eric Sampson pointed out in an e-mail that I could replace cell2mat with char, saving 4 characters. Thanks Eric!
Ruby 1.9 - 189 178 159 155 153 chars
f,n=$*
c=IO.read f
n.to_i.times{i=0;c=c.chars.map{|v|i+=1
v<?.?v:('...X'+v)[[83,2,-79].map{|j|c[i-j,3]}.to_s.count ?X]||?.}*''}
File.new('out.txt',?w)<<c
Edit:
Handles newlines with 4 chars less.
Can remove 7 more (v<?.?v:) if you allow it to clobber newlines when the live cells reach the edges.
perl, 127 129 135 chars
Managed to strip off a couple more characters...
$/=pop;#b=split'',<>;map{$n=-1;#b=map{++$n;/
/?$_:($t=grep/X/,#b[map{$n+$_,$n-$_}1,80..82])==3|$t+/X/==3?X:'.'}#b}1..$/;print#b
Python - 282 chars
might as well get the ball rolling...
import sys
_,I,N=sys.argv;R=range(3e3);B=open(I).read();B=set(k for k in R if'A'<B[k])
for k in R*int(N):
if k<1:b,B=B,set()
c=sum(len(set((k+o,k-o))&b)for o in(1,80,81,82))
if(c==3)+(c==2)*(k in b):B.add(k)
open('out.txt','w').write(''.join('.X\n'[(k in B)-(k%81<1)]for k in R))
Python 2.x - 210/234 characters
Okay, the 210-character code is kind of cheating.
#coding:l1
exec'xÚ=ŽA\nÂ#E÷sŠº1­ƒÆscS‰ØL™Æª··­âî¿GÈÿÜ´1iÖ½;Sçu.~H®J×Þ-‰­Ñ%ª.wê,šÖ§J®d꘲>cÉZË¢V䀻Eîa¿,vKAËÀå̃<»Gce‚ÿ‡ábUt¹)G%£êŠ…óbÒüíÚ¯GÔ/n×Xši&ć:})äðtÏÄJÎòDˆÐÿG¶'.decode('zip')
You probably won't be able to copy and paste this code and get it to work. It's supposed to be Latin-1 (ISO-8859-1), but I think it got perverted into Windows-1252 somewhere along the way. Additionally, your browser may swallow some of the non-ASCII characters.
So if it doesn't work, you can generate the file from plain-old 7-bit characters:
s = """
23 63 6F 64 69 6E 67 3A 6C 31 0A 65 78 65 63 27 78 DA 3D 8E 41 5C 6E C2
40 0C 45 F7 73 8A BA 31 13 AD 83 15 11 11 C6 73 08 63 17 05 53 89 D8 4C
99 C6 AA B7 B7 AD E2 EE BF 47 C8 FF DC B4 31 69 D6 BD 3B 53 E7 75 2E 7E
48 AE 4A D7 DE 90 8F 2D 89 AD D1 25 AA 2E 77 16 EA 2C 9A D6 A7 4A AE 64
EA 98 B2 3E 63 C9 5A CB A2 56 10 0F E4 03 80 BB 45 16 0B EE 04 61 BF 2C
76 0B 4B 41 CB C0 E5 CC 83 03 3C 1E BB 47 63 65 82 FF 87 E1 62 55 1C 74
B9 29 47 25 A3 EA 03 0F 8A 07 85 F3 62 D2 FC ED DA AF 11 47 D4 2F 6E D7
58 9A 69 26 C4 87 3A 7D 29 E4 F0 04 74 CF C4 4A 16 CE F2 1B 44 88 1F D0
FF 47 B6 27 2E 64 65 63 6F 64 65 28 27 7A 69 70 27 29
"""
with open('life.py', 'wb') as f:
f.write(''.join(chr(int(i, 16)) for i in s.split()))
The result of this is a valid 210-character Python source file. All I've done here is used zip compression on the original Python source code. The real cheat is that I'm using non-ASCII characters in the resultant string. It's still valid code, it's just cumbersome.
The noncompressed version weighs in at 234 characters, which is still respectable, I think.
import sys
f,f,n=sys.argv
e=open(f).readlines()
p=range
for v in p(int(n)):e=[''.join('.X'[8+16*(e[t][i]!='.')>>sum(n!='.'for v in e[t-1:t+2]for n in v[i-1:i+2])&1]for i in p(80))for t in p(40)]
open('out.txt','w').write('\n'.join(e))
Sorry about the horizontal scroll, but all newlines in the above are required, and I've counted them as one character each.
I wouldn't try to read the golfed code. The variable names are chosen randomly to achieve the best compression. Yes, I'm serious. A better-formatted and commented version follows:
# get command-line arguments: infile and count
import sys
ignored, infile, count = sys.argv
# read the input into a list (each input line is a string in the list)
data = open(infile).readlines()
# loop the number of times requested on the command line
for loop in range(int(count)):
# this monstrosity applies the rules for each iteration, replacing
# the cell data with the next generation
data = [''.join(
# choose the next generation's cell from '.' for
# dead, or 'X' for alive
'.X'[
# here, we build a simple bitmask that implements
# the generational rules. A bit from this integer
# will be chosen by the count of live cells in
# the 3x3 grid surrounding the current cell.
#
# if the current cell is dead, this bitmask will
# be 8 (0b0000001000). Since only bit 3 is set,
# the next-generation cell will only be alive if
# there are exactly 3 living neighbors in this
# generation.
#
# if the current cell is alive, the bitmask will
# be 24 (8 + 16, 0b0000011000). Since both bits
# 3 and 4 are set, this cell will survive if there
# are either 3 or 4 living cells in its neighborhood,
# including itself
8 + 16 * (data[y][x] != '.')
# shift the relevant bit into position
>>
# by the count of living cells in the 3x3 grid
sum(character != '.' # booleans will convert to 0 or 1
for row in data[y - 1 : y + 2]
for character in row[x - 1 : x + 2]
)
# select the relevant bit
& 1
]
# for each column and row
for x in range(80)
)
for y in range(40)
]
# write the results out
open('out.txt','w').write('\n'.join(data))
Sorry, Pythonistas, for the C-ish bracket formatting, but I was trying to make it clear what each bracket was closing.
Haskell - 284 272 232 chars
import System
main=do f:n:_<-getArgs;s<-readFile f;writeFile"out.txt"$t s$read n
p '\n'_='\n'
p 'X'2='X'
p _ 3='X'
p _ _='.'
t r 0=r
t r n=t[p(r!!m)$sum[1|d<-1:[80..82],s<-[1,-1],-m<=d*s,m+d*s<3240,'X'==r!!(m+d*s)]|m<-[0..3239]]$n-1
F#, 496
I could reduce this a lot, but I like this as it's still in the ballpark and pretty readable.
open System.IO
let mutable a:_[,]=null
let N y x=
[-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1]
|>Seq.sumBy(fun(i,j)->try if a.[y+i,x+j]='X' then 1 else 0 with _->0)
[<EntryPoint>]
let M(r)=
let b=File.ReadAllLines(r.[0])
a<-Array2D.init 40 80(fun y x->b.[y].[x])
for i=1 to int r.[1] do
a<-Array2D.init 40 80(fun y x->
match N y x with|3->'X'|2 when a.[y,x]='X'->'X'|_->'.')
File.WriteAllLines("out.txt",Array.init 40(fun y->
System.String(Array.init 80(fun x->a.[y,x]))))
0
EDIT
428
By request, here's my next stab:
open System
let mutable a,k=null,Array2D.init 40 80
[<EntryPoint>]
let M r=
a<-k(fun y x->IO.File.ReadAllLines(r.[0]).[y].[x])
for i=1 to int r.[1] do a<-k(fun y x->match Seq.sumBy(fun(i,j)->try if a.[y+i,x+j]='X'then 1 else 0 with _->0)[-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1]with|3->'X'|2 when a.[y,x]='X'->'X'|_->'.')
IO.File.WriteAllLines("out.txt",Array.init 40(fun y->String(Array.init 80(fun x->a.[y,x]))))
0
That's a 14% reduction with some basic golfing. I can't help but feel that I'm losing by using a 2D-array/array-of-strings rather than a 1D array, but don't feel like doing that transform now. Note how I elegantly read the file 3200 times to initialize my array :)
Ruby 1.8: 178 175 chars
f,n=$*;b=IO.read f
n.to_i.times{s=b.dup
s.size.times{|i|t=([82,1,-80].map{|o|b[i-o,3]||''}*'').count 'X'
s[i]=t==3||b[i]-t==?T??X:?.if s[i]>13};b=s}
File.new('out.txt','w')<<b
Newlines are significant (although all can be replaced w/ semicolons.)
Edit: fixed the newline issue, and trimmed 3 chars.
Java, 441... 346
Update 1 Removed inner if and more ugliness
Update 2 Fixed a bug and gained a character
Update 3 Using lots more memory and arrays while ignoring some boundaries issues. Probably a few chars could be saved.
Update 4 Saved a few chars. Thanks to BalusC.
Update 5 A few minor changes to go below 400 and make it just that extra bit uglier.
Update 6 Now things are so hardcoded may as well read in the exact amount in one go. Plus a few more savings.
Update 7 Chain the writing to the file to save a char. Plus a few odd bits.
Just playing around with BalusC's solution. Limited reputation means I couldnt add anything as a comment to his.
class M{public static void main(String[]a)throws Exception{int t=3240,j=t,i=new Integer(a[1])*t+t;char[]b=new char[i+t],p={1,80,81,82};for(new java.io.FileReader(a[0]).read(b,t,t);j<i;){char c=b[j],l=0;for(int n:p)l+=b[j+n]/88+b[j-n]/88;b[j+++t]=c>10?(l==3|l+c==90?88:'.'):c;}new java.io.FileWriter("out.txt").append(new String(b,j,t)).close();}}
More readable(?) version:
class M{
public static void main(String[]a)throws Exception{
int t=3240,j=t,i=new Integer(a[1])*t+t;
char[]b=new char[i+t],p={1,80,81,82};
for(new java.io.FileReader(a[0]).read(b,t,t);j<i;){
char c=b[j],l=0;
for(int n:p)l+=b[j+n]/88+b[j-n]/88;
b[j+++t]=c>10?(l==3|l+c==90?88:'.'):c;
}
new java.io.FileWriter("out.txt").append(new String(b,j,t)).close();
}
}
Scala - 467 364 339 chars
object G{def main(a:Array[String]){val l=io.Source.fromFile(new java.io.File(a(0)))getLines("\n")map(_.toSeq)toSeq
val f=new java.io.FileWriter("out.txt")
f.write((1 to a(1).toInt).foldLeft(l){(t,_)=>(for(y<-0 to 39)yield(for(x<-0 to 79)yield{if(x%79==0|y%39==0)'.'else{val m=t(y-1)
val p=t(y+1);val s=Seq(m(x-1),m(x),m(x+1),t(y)(x-1),t(y)(x+1),p(x-1),p(x),p(x+1)).count('X'==_)
if(s==3|(s==2&t(y)(x)=='X'))'X'else'.'}})toSeq)toSeq}map(_.mkString)mkString("\n"))
f.close}}
I think there is much room for improvement...
[Edit] Yes, it is:
object G{def main(a:Array[String]){var l=io.Source.fromFile(new java.io.File(a(0))).mkString
val f=new java.io.FileWriter("out.txt")
var i=a(1).toInt
while(i>0){l=l.zipWithIndex.map{case(c,n)=>if(c=='\n')'\n'else{val s=Seq(-83,-82,-81,-1,1,81,82,83).map(_+n).filter(k=>k>=0&k<l.size).count(l(_)=='X')
if(s==3|(s==2&c=='X'))'X'else'.'}}.mkString
i-=1}
f.write(l)
f.close}}
[Edit] And I have the feeling there is still more to squeeze out...
object G{def main(a:Array[String]){val f=new java.io.FileWriter("out.txt")
f.write(((1 to a(1).toInt):\(io.Source.fromFile(new java.io.File(a(0))).mkString)){(_,m)=>m.zipWithIndex.map{case(c,n)=>
val s=Seq(-83,-82,-81,-1,1,81,82,83)count(k=>k+n>=0&k+n<m.size&&m(k+n)=='X')
if(c=='\n')c else if(s==3|s==2&c=='X')'X'else'.'}.mkString})
f.close}}
The following solution uses my own custom domain-specific programming language which I have called NULL:
3499538
In case you are wondering how this works: My language consists of only of one statment per program. The statement represents a StackOverflow thread ID belonging to a code golf thread. My compiler compiles this into a program that looks for the best javascript solution (with the SO API), downloads it and runs it in a web browser.
Runtime could be better for new threads (it may take some time for the first upvoted Javascript answer to appear), but on the upside it requires only very little coding skills.
Javascript/Node.js - 233 236 characters
a=process.argv
f=require('fs')
m=46
t=f.readFileSync(a[2])
while(a[3]--)t=[].map.call(t,function(c,i){for(n=g=0;e=[-82,-81,-80,-1,1,80,81,82][g++];)t[i+e]>m&&n++
return c<m?c:c==m&&n==3||c>m&&n>1&&n<4?88:m})
f.writeFile('out.txt',t)
C - 300
Just wondered how much smaller and uglier my java solution could go in C. Reduces to 300 including the newlines for the preprocessor bits. Leaves freeing the memory to the OS! Could save ~20 by assuming the OS will close and flush the file too.
#include<stdio.h>
#include<stdlib.h>
#define A(N)j[-N]/88+j[N]/88
int main(int l,char**a){
int t=3240,i=atoi(a[2])*t+t;
char*b=malloc(i+t),*j;
FILE*f;
fread(j=b+t,1,t,fopen(a[1],"r"));
for(;j-b-i;j++[t]=*j>10?l==3|l+*j==90?88:46:10)
l=A(1)+A(80)+A(81)+A(82);
fwrite(j,1,t,f=fopen("out.txt","w"));
fclose(f);
}
MUMPS: 314 chars
L(F,N,R=40,C=80)
N (F,N,R,C)
O F:"RS" U F D C F
.F I=1:1:R R L F J=1:1:C S G(0,I,J)=($E(L,J)="X")
F A=0:1:N-1 F I=1:1:R F J=1:1:C D S G(A+1,I,J)=$S(X=2:G(A,I,J),X=3:1,1:0)
.S X=0 F i=-1:1:1 F j=-1:1:1 I i!j S X=X+$G(G(A,I+i,J+j))
S F="OUT.TXT" O F:"WNS" U F D C F
.F I=1:1:R F J=1:1:C W $S(G(N,I,J):"X",1:".") W:J=C !
Q
Java, 556 532 517 496 472 433 428 420 418 381 chars
Update 1: replaced 1st StringBuffer by Appendable and 2nd by char[]. Saved 24 chars.
Update 2: found a shorter way to read file into char[]. Saved 15 chars.
Update 3: replaced one if/else by ?: and merged char[] and int declarations. Saved 21 chars.
Update 4: replaced (int)f.length() and c.length by s. Saved 24 chars.
Update 5: made improvements as per hints of Molehill. Major one was hardcoding the char length so that I could get rid of File. Saved 39 chars.
Update 6: minor refactoring. Saved 6 chars.
Update 7: replaced Integer#valueOf() by new Integer() and refactored for loop. Saved 8 chars.
Update 8: Improved neighbour calculation. Saved 2 chars.
Update 9: Optimized file reading since file length is already hardcoded. Saved 37 chars.
import java.io.*;class L{public static void main(String[]a)throws Exception{int i=new Integer(a[1]),j,l,s=3240;int[]p={-82,-81,-80,-1,1,80,81,82};char[]o,c=new char[s];for(new FileReader(a[0]).read(c);i-->0;c=o)for(o=new char[j=s];j-->0;){l=0;for(int n:p)l+=n+j>-1&n+j<s?c[n+j]/88:0;o[j]=c[j]>13?l==3|l+c[j]==90?88:'.':10;}Writer w=new FileWriter("out.txt");w.write(c);w.close();}}
More readable version:
import java.io.*;
class L{
public static void main(String[]a)throws Exception{
int i=new Integer(a[1]),j,l,s=3240;
int[]p={-82,-81,-80,-1,1,80,81,82};
char[]o,c=new char[s];
for(new FileReader(a[0]).read(c);i-->0;c=o)for(o=new char[j=s];j-->0;){
l=0;for(int n:p)l+=n+j>-1&n+j<s?c[n+j]/88:0;
o[j]=c[j]>10?l==3|l+c[j]==90?88:'.':10;
}
Writer w=new FileWriter("out.txt");w.write(c);w.close();
}
}
Closing after writing is absoletely mandatory, else the file is left empty. It would otherwise have saved another 21 chars.
Further I could also save one more char when I use 46 instead of '.', but both javac and Eclipse jerks with a compilation error Possible loss of precision. Weird stuff.
Note: this expects an input file with \n newlines, not \r\n as Windows by default uses!
PHP - 365 328 322 Characters.
list(,$n,$l) = $_SERVER["argv"];
$f = file( $n );
for($j=0;$j<$l;$j++){
foreach($f as $k=>$v){
$a[$k]="";
for($i=0;$i < strlen( $v );$i++ ){
$t = 0;
for($m=-1;$m<2;$m++){
for($h=-1;$h<2;$h++){
$t+=ord($f[$k + $m][$i + $h]);
}
}
$t-=ord($v[$i]);
$a[$k] .= ( $t == 494 || ($t == 452 && ord($v[$i])==88)) ? "X" : "." ;
}
}
$f = $a;
}
file_put_contents("out.txt", implode("\n", $a ));
I'm sure this can be improved upon but I was curious what it would look like in PHP. Maybe this will inspire someone who has a little more code-golf experience.
Updated use list() instead of $var = $_SERVER["argv"] for both args. Nice one Don
Updated += and -= this one made me /facepalm heh cant believe i missed it
Updated file output to use file_put_contents() another good catch by Don
Updated removed initialization of vars $q and $w they were not being used
R 340 chars
cgc<-function(i="in.txt",x=100){
require(simecol)
z<-file("in.txt", "rb")
y<-matrix(data=NA,nrow=40,ncol=80)
for(i in seq(40)){
for(j in seq(80)){
y[i,j]<-ifelse(readChar(z,1) == "X",1,0)
}
readChar(z,3)
}
close(z)
init(conway) <- y
times(conway)<-1:x
o<-as.data.frame(out(sim(conway))[[100]])
write.table(o, "out.txt", sep="", row.names=FALSE, col.names=FALSE)
}
cgc()
I feel it's slightly cheating to have an add in package that does the actual automata for you, but I'm going with it cos I still had to thrash around with matricies and stuff to read in the file with 'X' instead of 1.
This is my first 'code golf', interesting....
c++ - 492 454 386
my first code golf ;)
#include<fstream>
#define B(i,j)(b[i][j]=='X')
int main(int i,char**v){for(int n=0;n<atoi(v[2]);++n){std::ifstream f(v[1]);v[1]="out.txt";char b[40][83];for(i=0;i<40;++i)f.getline(b[i],83);std::ofstream g("out.txt");g<<b[0]<<'\n';for(i=1;i<39;++i){g<<'.';for(int j=1;j<79;++j){int k=B(i-1,j)+B(i+1,j)+B(i,j-1)+B(i,j+1)+B(i-1,j-1)+B(i+1,j+1)+B(i+1,j-1)+B(i-1,j+1);(B(i,j)&&(k<2||k>3))?g<<'.':(!B(i,j)&&k==3)?g<<'X':g<<b[i][j];}g<<".\n";}g<<b[0]<<'\n';}}
A somewhat revised version, replacing some of the logic with a table lookup+a few other minor tricks:
#include<fstream>
#define B(x,y)(b[i+x][j+y]=='X')
int main(int i,char**v){for(int n=0;n<atoi(v[2]);++n){std::ifstream f(v[1]);*v="out.txt";char b[40][83], O[]="...X.....";for(i=0;i<40;++i)f>>b[i];std::ofstream g(*v);g<<b[0]<<'\n';for(i=1;i<39;++i){g<<'.';for(int j=1;j<79;++j){O[2]=b[i][j];g<<O[B(-1,0)+B(1,0)+B(0,-1)+B(0,1)+B(-1,-1)+B(1,1)+B(1,-1)+B(-1,1)];}g<<".\n";}g<<b[0]<<'\n';}}
Perl – 214 chars
What, no perl entries yet?
$i=pop;#c=<>;#c=map{$r=$_;$u='';for(0..79)
{$K=$_-1;$R=$r-1;$u.=((&N.(&N^"\0\W\0").&N)=~y/X//
|(substr$c[$r],$_,1)eq'X')==3?'X':'.';}$u}keys#c for(1..$i);
sub N{substr$c[$R++],$K,3}open P,'>','out.txt';$,=$/;print P#c
Run with: conway.pl infile #times
Another Java attempt, 361 chars
class L{public static void main(final String[]a)throws Exception{new java.io.RandomAccessFile("out.txt","rw"){{int e=88,p[]={-1,1,-80,80,-81,81,-82,82},s=3240,l=0,i=new Byte(a[1])*s+s,c;char[]b=new char[s];for(new java.io.FileReader(a[0]).read(b);i>0;seek(l=++l%s),i--){c=b[l];for(int n:p)c+=l+n>=0&l+n<s?b[l+n]/e:0;write(c>13?(c==49|(c|1)==91?e:46):10);}}};}}
And a little more readable
class L {
public static void main(final String[]a) throws Exception {
new java.io.RandomAccessFile("out.txt","rw"){{
int e=88, p[]={-1,1,-80,80,-81,81,-82,82},s=3240,l=0,i=new Byte(a[1])*s+s,c;
char[] b = new char[s];
for (new java.io.FileReader(a[0]).read(b);i>0;seek(l=++l%s),i--) {
c=b[l];
for (int n:p)
c+=l+n>=0&l+n<s?b[l+n]/e:0;
write(c>13?(c==49|(c|1)==91?e:46):10);
}
}};
}
}
Very similar to Molehill’s version. I've tried to use a different FileWriter and to count the cell's neighbors without an additional variable.
Unfortunately, RandomAccessFile is a pretty long name and it is required that you pass an file access mode.
RUST - 469 characters
Don't know if I should post this here, (this post is 3 years old) but anyway, my try on this, in rust (0.9):
use std::io::fs::File;fn main(){
let mut c=File::open(&Path::new(std::os::args()[1])).read_to_end();
for _ in range(0,from_str::<int>(std::os::args()[2]).unwrap()){
let mut b=c.clone();for y in range(0,40){for x in range(0,80){let mut s=0;
for z in range(x-1,x+2){for t in range(y-1,y+2){
if z>=0&&t>=0&&z<80&&t<40&&(x !=z||y !=t)&&c[t*81+z]==88u8{s +=1;}}}
b[y*81+x]=if s==3||(s==2&&c[y*81+x]==88u8){88u8} else {46u8};}}c = b;}
File::create(&Path::new("out.txt")).write(c);}
For people interested, here is the code before some agressive golfing:
use std::io::fs::File;
fn main() {
let f = std::os::args()[1];
let mut c = File::open(&Path::new(f)).read_to_end();
let n = from_str::<int>(std::os::args()[2]).unwrap();
for _ in range(0,n)
{
let mut new = c.clone();
for y in range(0,40) {
for x in range(0,80) {
let mut sum = 0;
for xx in range(x-1,x+2){
for yy in range(y-1,y+2) {
if xx >= 0 && yy >= 0 && xx <80 && yy <40 && (x != xx || y != yy) && c[yy*81+xx] == 88u8
{ sum = sum + 1; }
}
}
new[y*81+x] = if sum == 3 || (sum == 2 && c[y*81+x] == 88u8) {88u8} else {46u8};
}
}
c = new;
}
File::create(&Path::new("out.txt")).write(c);
}
ét voilà
you may want to use this html file. no file input, but a textarea that does the job!
there is also some html and initiation and vars. the main routine has only 235 characters.
It's hand-minified JS.
<!DOCTYPE html>
<html><body><textarea id="t" style="width:600px;height:600px;font-family:Courier">
</textarea></body><script type="text/javascript">var o,c,m=new Array(3200),
k=new Array(3200),y,v,l,p;o=document.getElementById("t");for(y=0;y<3200;y++)
{m[y]=Math.random()<0.5;}setInterval(function(){p="";for(y=0;y<3200;y++){c=0;
for(v=-1;v<2;v+=2){c+=m[y-1*v]?1:0;for(l=79;l<82;l++)c+=m[y-l*v]?1:0;}
k[y]=c==3||m[y]&&c==2;}p="";for(y=0;y<3200;y++){p+=(y>0&&y%80==0)?"\n":"";
m[y]=k[y];p+=(m[y]?"O":"-");}o.innerHTML=p;},100);</script></html>
One of the classic patterns
***
..*
.*
My avatar was created using my version of the Game of Life using this pattern and rule(note that it is not 23/3):
#D Thanks to my daughter Natalie
#D Try at cell size of 1
#R 8/1
#P -29 -29
.*********************************************************
*.*******************************************************.*
**.*****************************************************.**
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
****************************.*.****************************
***********************************************************
****************************.*.****************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
**.*****************************************************.**
*.*******************************************************.*
.*********************************************************
IMHO - as I learned Conway's Game of Life the trick wasn't writing short code, but code that could do complex life forms quickly. Using the classic pattern above and a wrapped world of 594,441 cells the best I could ever do was around 1,000 generations / sec.
Another simple pattern
**********
.
................*
.................**
................**.......**********
And gliders
........................*...........
......................*.*...........
............**......**............**
...........*...*....**............**
**........*.....*...**..............
**........*...*.**....*.*...........
..........*.....*.......*...........
...........*...*....................
............**......................

Code Golf: Four is magic

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The puzzle
A little puzzle I heard while I was in high school went something like this...
The questioner would ask me to give him a number;
On hearing the number, the questioner would do some sort of transformation on it repeatedly (for example, he might say ten is three) until eventually arriving at the number 4 (at which point he would finish with four is magic).
Any number seems to be transformable into four eventually, no matter what.
The goal was to try to figure out the transformation function and then be able to reliably proctor this puzzle yourself.
The solution
The transformation function at any step was to
Take the number in question,
Count the number of letters in its English word representation, ignoring a hyphen or spaces or "and" (e.g., "ten" has 3 letters in it, "thirty-four" has 10 letters in it, "one hundred forty-three" has 20 letters in it).
Return that number of letters.
For all of the numbers I have ever cared to test, this converges to 4. Since "four" also has four letters in it, there would be an infinite loop here; instead it is merely referred to as magic by convention to end the sequence.
The challenge
Your challenge is to create a piece of code that will read a number from the user and then print lines showing the transformation function being repeatedly applied until "four is magic" is reached.
Specifically:
Solutions must be complete programs in and of themselves. They cannot merely be functions which take in a number-- factor in the input.
Input must be read from standard input. (Piping from "echo" or using input redirection is fine since that also goes from stdin)
The input should be in numeric form.
For every application of the transformation function, a line should be printed: a is b., where a and b are numeric forms of the numbers in the transformation.
Full stops (periods) ARE required!
The last line should naturally say, 4 is magic..
The code should produce correct output for all numbers from 0 to 99.
Examples:
> 4
4 is magic.
> 12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.
> 42
42 is 8.
8 is 5.
5 is 4.
4 is magic.
> 0
0 is 4.
4 is magic.
> 99
99 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.
The winner is the shortest submission by source code character count which is also correct.
BONUS
You may also try to write a version of the code which prints out the ENGLISH NAMES for the numbers with each application of the transformation function. The original input is still numeric, but the output lines should have the word form of the number.
(Double bonus for drawing shapes with your code)
(EDIT) Some clarifications:
I do want the word to appear on both sides in all applicable cases, e.g. Nine is four. Four is magic.
I don't care about capitalization, though. And I don't care how you separate the word tokens, though they should be separated: ninety-nine is okay, ninety nine is okay, ninetynine is not okay.
I'm considering these a separate category for bonus competition with regard to the challenge, so if you go for this, don't worry about your code being longer than the numeric version.
Feel free to submit one solution for each version.
Perl, about 147 char
Loosely based on Platinum Azure's solution:
chop
($_.=
<>);#
u="433
5443554
366 887
798 866
555 766
"=~ /\d
/gx ;#4
sub r{4
-$_ ?$_
<20 ?$u
[$_ ]:(
$'? $u[
$'] :0)
+$u[18+$&]:magic}print"
$_ is ",$_=r(),'.'while
/\d
/x;
444
GolfScript - 101 96 93 92 91 90 94 86 bytes
90 → 94: Fixed output for multiples of 10.
94 → 86: Restructured code. Using base 100 to remove non-printable characters.
86 → 85: Shorter cast to string.
{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Common Lisp 157 Chars
New more conforming version, now reading form standard input and ignoring spaces and hyphens:
(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))
In human-readable form:
(labels ((g (x)
(if (= x 4)
(princ "4 is magic.")
(let ((n (length (remove-if (lambda(x) (find x " -"))
(format nil "~r" x)))))
(format t"~a is ~a.~%" x n)
(g n)))))
(g (read)))
And some test runs:
>24
24 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.
>23152436
23152436 is 64.
64 is 9.
9 is 4.
4 is magic.
And the bonus version, at 165 chars:
(labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))
Giving
>24
twenty-four is ten.
ten is three.
three is five.
five is four.
four is magic.
>234235
two hundred thirty-four thousand two hundred thirty-five is forty-eight.
forty-eight is ten.
ten is three.
three is five.
five is four.
four is magic.
Python 2.x, 144 150 154 166 chars
This separates the number into tens and ones and sum them up. The undesirable property of the pseudo-ternary operator a and b or c that c is returned if b is 0 is being abused here.
n=input()
x=0x4d2d0f47815890bd2
while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p
print"4 is magic."
The previous naive version (150 chars). Just encode all lengths as an integer.
n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."
C - with number words
445 431 427 421 399 386 371 359* 356 354† 348 347 characters
That's it. I don't think I can make this any shorter.
All newlines are for readability and can be removed:
i;P(x){char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,
fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,
4RmagicS,zero,";while(x--)if(*++p-44&&!x++)*p>95|*p<48?putchar(*p),++i:P(*p-48);
}main(c){for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))P(c?c>19?P(c/10+18),
(c%=10)&&putchar(45):0,c:37);P(36);}
Below, it is somewhat unminified, but still pretty hard to read. See below for a more readable version.
i;
P(x){
char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";
while(x--)
if(*++p-44&&!x++)
*p>95|*p<48?putchar(*p),++i:P(*p-48);
}
main(c){
for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))
P(c?
c>19?
P(c/10+18),
(c%=10)&&
putchar(45)
:0,
c
:37);
P(36);
}
Expanded and commented:
int count; /* type int is assumed in the minified version */
void print(int index){ /* the minified version assumes a return type of int, but it's ignored */
/* see explanation of this string after code */
char *word =
/* 1 - 9 */
",one,two,three,four,five,six,sM,eight,nine,"
/* 10 - 19 */
"tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,"
/* 20 - 90, by tens */
"twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,"
/* lookup table */
"en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";
while(index >= 0){
if(*word == ',')
index--;
else if(index == 0) /* we found the right word */
if(*word >= '0' && *word < 'a') /* a compression marker */
print(*word - '0'/*convert to a number*/);
else{
putchar(*word); /* write the letter to the output */
++count;
}
++word;
}
}
int main(int argc, char **argv){ /* see note about this after code */
scanf("%d", &argc); /* parse user input to an integer */
while(argc != 4){
count = 0;
if(argc == 0)
print(37/*index of "zero"*/);
else{
if(argc > 19){
print(argc / 10/*high digit*/ + 20/*offset of "twenty"*/ - 2/*20 / 10*/);
argc %= 10; /* get low digit */
if(argc != 0) /* we need a hyphen before the low digit */
putchar('-');
}
print(argc/* if 0, then nothing is printed or counted */);
}
argc = count;
print(34/*" is "*/);
print(argc); /* print count as word */
print(35/*".\n"*/);
}
print(36/*"four is magic.\n"*/);
}
About the encoded string near the beginning
The names of the numbers are compressed using a very simple scheme. Frequently used substrings are replaced with one-character indices into the name array. A "lookup table" of extra name entries is added to the end for substrings not used in their entirety in the first set. Lookups are recursive: entries can refer to other entries.
For instance, the compressed name for 11 is elM. The print() function outputs the characters e and l (lower-case 'L', not number '1') verbatim, but then it finds the M, so it calls itself with the index of the 29th entry (ASCII 'M' - ASCII '0') into the lookup table. This string is evL, so it outputs e and v, then calls itself again with the index of the 28th entry in the lookup table, which is en, and is output verbatim. This is useful because en is also used in eL for een (used after eight in eighteen), which is used in tO for teen (used for every other -teen name).
This scheme results in a fairly significant compression of the number names, while requiring only a small amount of code to decompress.
The commas at the beginning and end of the string account for the simplistic way that substrings are found within this string. Adding two characters here saves more characters later.
About the abuse of main()
argv is ignored (and therefore not declared in the compressed version), argc's value is ignored, but the storage is reused to hold the current number. This just saves me from having to declare an extra variable.
About the lack of #include
Some will complain that omitting #include <stdio.h> is cheating. It is not at all. The given is a completely legal C program that will compile correctly on any C compiler I know of (albeit with warnings). Lacking protoypes for the stdio functions, the compiler will assume that they are cdecl functions returning int, and will trust that you know what arguments to pass. The return values are ignored in this program, anyway, and they are all cdecl ("C" calling convention) functions, and we do indeed know what arguments to pass.
Output
Output is as expected:
0
zero is four.
four is magic.
1
one is three.
three is five.
five is four.
four is magic.
4
four is magic.
20
twenty is six.
six is three.
three is five.
five is four.
four is magic.
21
twenty-one is nine.
nine is four.
four is magic.
* The previous version missed the mark on two parts of the spec: it didn't handle zero, and it took input on the command line instead of stdin. Handling zeros added characters, but using stdin instead of command line args, as well as a couple of other optimzations saved the same number of characters, resulting in a wash.
† The requirements have been changed to make clear that the number word should be printed on both sides of " is ". This new version meets that requirement, and implements a couple more optimizations to (more than) account for the extra size necessary.
J, 107 112 characters
'4 is magic.',~}:('.',~":#{.,' is ',":#{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:
(Newline for readability only)
Usage and output:
'4 is magic.',~}:('.',~":#{.,' is ',":#{:)"1]2&{.\.(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.
T-SQL, 413 451 499 chars
CREATE FUNCTION d(#N int) RETURNS int AS BEGIN
Declare #l char(50), #s char(50)
Select #l='0066555766',#s='03354435543668877987'
if #N<20 return 0+substring(#s,#N+1,1) return 0+substring(#l,(#N/10)+1,1) + 0+(substring(#s,#N%10+1,1))END
GO
CREATE proc M(#x int) as BEGIN
WITH r(p,n)AS(SELECT p=#x,n=dbo.d(#x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,'is',n,'.' from r print '4 is magic.'END
(Not that I'm seriously suggesting you'd do this... really I just wanted to write a CTE)
To use:
M 95
Returns
p n
----------- ---- -----------
95 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.
Java (with boilerplate), 308 290 286 282 280 characters
class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}
I'm sure Groovy would get rid of much of that.
Explanation and formatting (all comments, newlines and leading/trailing whitespace removed in count):
Reasonably straight forward, but
//boilerplate
class A{
public static void main(String[]a){
//i is current/left number, j right/next number. i=4 signals to start
//by reading input
int i=4,j=0;
for(;;)
//print in the form "<left> is <right>."
System.out.printf(
"%d is %s.%n",
i=i==4?
//<left>: if i is 4 <left> will be a new starting number
new java.util.Scanner(System.in).nextInt():
//otherwise it's the next val
j,
i!=4?
//use string to map number to its length (:;< come after 9 in ASCII)
//48 is value of '0'. store in j for next iteration
j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:
//i==4 is special case for right; print "magic"
"magic");
}
}
Edit: No longer use hex, this is less keystrokes
Windows PowerShell: 152 153 184 bytes
based on the previous solution, with more influence from other solutions
$o="03354435543668877988"
for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a
"$a is $b."}'4 is magic.'
C, 158 characters
main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d.\n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}
(originally based on Vlad's Python code, borrowed a trick from Tom Sirgedas' C++ solution to squeeze out a few more characters)
expanded version:
main(n, c) {
char *d = "03354435543668877988";
for (scanf("%d",&n); n-4; n = c)
printf("%d is %d.\n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10] : 4);
puts("4 is magic.");
}
Python, 129 133 137 148 chars
As a warm-up, here is my first version (improves couple of chars over previous best Python).
PS. After a few redactions now it is about twenty char's shorter:
n=input()
while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,'is %d.'%p;n=p
print'4 is magic.'
C#: 210 Characters.
Squished:
using C=System.Console;class B{static void Main(){int
x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}.\n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}
Expanded:
using C=System.Console;
class B
{
static void Main()
{
int x=0,y=int.Parse(C.ReadLine());
while(x!=4)
C.Write((x=y)+" is {0}.\n",
x==4?
"magic":
""+(y= x==0?
4:
"03354435543668877988"[x<20?x:x%10]+
"0066555766"[x/10]-96)
);
}
}
Tricks this approach uses:
Create a lookup table for number name lengths based on digits that appear in the number.
Use character array lookup on a string, and char arithmetic instead of a numeric array.
Use class name aliasing to short Console. to C.
Use the conditional (ternary) operator (?:) instead of if/else.
Use the \n with Write escape code instead of WriteLine
Use the fact that C# has a defined order of evaluation to allow assignments inside the Write function call
Use the assignment expressions to eliminate extra statements, and thus extra braces
Perl: 148 characters
(Perl: 233 181 212 206 200 199 198 185 179 149 148 characters)
Moved exceptions hash into unit array. This resulted in my being able to cut a lot of characters :-)
mobrule pointed out a nasty bug. Quick fix adds 31 characters, ouch!
Refactored for zero special case, mild golfing done as well.
Direct list access for single use rather than storing to array? Hell yes!
SO MUCH REFACTORING for just ONE bloody character. This, truly, is the life of a golfer. :-(
Oops, easy whitespace fix. 198 now.
Refactored some redundant code.
Last return keyword in r is unnecessary, shaved some more off.
Massive refactoring per comments; unfortunately I could only get it to 149 because I had to fix a bug that was present in both my earlier code and the commenters' versions.
Trying bareword "magic".
Let's get this ball rolling with a modest attempt in Perl.
#u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_
Tricks:
Too many!
JavaScript 1.8 (SpiderMonkey) - 153 Chars
l='4335443554366887798866555766'.split('')
for(b=readline();(a=+b)-4;print(a,'is '+b+'.'))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10])
print('4 is magic.')
Usage: echo 42 | js golf.js
Output:
42 is 8.
8 is 5.
5 is 4.
4 is magic.
With bonus - 364 chars
l='zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ')
z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?' '+l[a%10]:'')
for(b=+readline();(a=b)-4;print(z(a),'is '+z(b)+'.'))b=z(a).replace(' ','').length
print('four is magic.')
Output:
ninety nine is ten.
ten is three.
three is five.
five is four.
four is magic.
Haskell, 224 270 characters
o="43354435543668877988"
x!i=read[x!!i]
n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10
f x=zipWith(\a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"]
main=readLn>>=mapM putStrLn.f
And little more readable -
ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8]
tens = [0,0,6,6,5,5,5,7,6,6]
n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10)
f x = zipWith (\a b -> a ++ " is " ++ b ++ ".") l (tail l)
where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"]
main = readLn >>= mapM putStrLn . f
C++ Stdio version, minified: 196 characters
#include <cstdio>
#define P;printf(
char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d.\n%d",p,p);}P" is magic.\n");}
C++ Iostreams version, minified: 195 characters
#include <iostream>
#define O;std::cout<<
char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<".\n"<<p;}O" is magic.\n";}
Original, un-minified: 344 characters
#include <cstdio>
int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 };
int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 };
int n(int n) {
return n<20 ? ones[n] : tens[n/10] + ones[n%10];
}
int main(int p) {
scanf("%d", &p);
while(p!=4) {
int q = n(p);
printf("%i is %i\n", p, q);
p = q;
}
printf("%i is magic\n", p);
}
Delphi: 329 characters
Single Line Version:
program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A='EDDFEEDFFEDGGIIHHJII';B='DGGFFFJGG';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write('> ');ReadLn(X);repeat Y:=Z(X);WriteLn(Format('%d is %d.',[X,Y]));X:=Y;until X=4;WriteLn('4 is magic.');end.
Formated:
program P;
{$APPTYPE CONSOLE}
uses
SysUtils;
const
S = 65;
A = 'EDDFEEDFFEDGGIIHHJII';
B = 'DGGFFFJGG';
function Z(X:Byte):Byte;
begin
if X<20
then Z := Ord(A[X+1])-S
else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10);
end;
var
X,Y: Byte;
begin
Write('> ');
ReadLn(X);
repeat
Y:=Z(X);
WriteLn(Format('%d is %d.' , [X,Y]));
X:=Y;
until X=4;
WriteLn('4 is magic.');
end.
Probably room for some more squeezing... :-P
C# 314 286 283 274 289 273 252 chars.
Squished:
252
Normal:
using C = System.Console;
class P
{
static void Main()
{
var x = "4335443554366877798866555766";
int m, o, v = int.Parse(C.ReadLine());
do {
C.Write("{0} is {1}.\n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48));
} while (o != 4);
C.ReadLine();
}
}
Edit Dykam: Did quite some carefull insertions and changes:
Changed the l.ToString() into a cast to object of the string "magic".
Created a temporary variable o, so I could move the break outside the for loop, that is, resulting in a do-while.
Inlined the o assignment, aswell the v assignment, continueing in inserting the calculation of l in the function arguments altogether, removing the need for l. Also inlined the assignment of m.
Removed a space in int[] x, int[]x is legit too.
Tried to transform the array into a string transformation, but the using System.Linq was too much to make this an improvement.
Edit 2 Dykam
Changed the int array to a char array/string, added proper arithmics to correct this.
Lua, 176 Characters
o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."
or
o={[0]=4,3,3,5,4,4
,3,5,5,4,3,6,6,8,8
,7,7,9,8,8}t={3,6,
6,5,5,5,7,6,6}n=
0+io.read()while
n ~= 4 do a= o[n
]or o[n%10]+t[(n
-n%10)/10]print(
n.." is "..a.."." )n=a
end print"4 is magic."
C - without number words
180 175* 172 167 characters
All newlines are for readability and can be removed:
i;V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}main(c){for(scanf("%d",&c);
c-4;)i=c,printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);puts(
"4 is magic.");}
Slightly unminified:
i;
V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}
main(c){
for(scanf("%d",&c);c-4;)
i=c,
printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);
puts("4 is magic.");
}
* The previous version missed the mark on two parts of the spec: it didn't handle zero, and it took input on the command line instead of stdin. Handling zero added characters, but using stdin instead of command line args saved even more, resulting in a net savings.
perl, 123 122 characters
Just realized that there is no requirement to output to STDOUT, so output to STDERR instead and knock off another character.
#u='0335443554366887798866555766'=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,".\n"until/g/
And, a version that returns spelled out numbers:
279 278 276 280 characters
#p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);#n=("",One,Two,Three,Four,Five,#p[3..6],Ten,Eleven,Twelve,map$_.teen,#p);s/u//for#m=map$_.ty,Twen,#p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/
While that meets the spec, it is not 100% well formatted. It returns an extra space after numbers ending in zero. The spec does say:
"I don't care how you separate the word tokens, though they should be separated"
That's kind of weaselly though.
A more correct version at
282 281 279 283 characters
#p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);#n=("\x8",One,Two,Three,Four,Five,#p[3..6],Ten,Eleven,Twelve,map$_.teen,#p);s/u//for#m=map$_.ty,Twen,#p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/
Python:
#!/usr/bin/env python
# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens = ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )
def Count(n):
if n > 10 and n < 20: return Teens[n-11]
return Smalls[n % 10 ] + Decades [ n / 10 ]
N = input()
while N-4:
Cnt = Count(N)
print "%d is %d" % ( N, Cnt)
N = Cnt
print "4 is magic"
C++, 171 characters (#include omitted)
void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d.\n",x,y);puts("4 is magic.");}
Ruby, 164 characters
n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."
decoded:
n = gets.to_i
s = "03354435543668877987"
if n == 0
puts "0 is 4."
else
puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4
end
puts "4 is magic."
Lua 185 190 199
added periods, added io.read, removed ()'s on last print
n=io.read();while(n~=4)do m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;print(n,' is ',m,'.')n=m;end print'4 is magic.'
with line breaks
n=io.read()
while (n~=4) do
m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;
print(n,' is ',m,'.')
n=m;
end
print'4 is magic.'
PhP Code
function get_num_name($num){
switch($num){
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';
}
}
function num_to_words($number, $real_name, $decimal_digit, $decimal_name){
$res = '';
$real = 0;
$decimal = 0;
if($number == 0)
return 'Zero'.(($real_name == '')?'':' '.$real_name);
if($number >= 0){
$real = floor($number);
$decimal = number_format($number - $real, $decimal_digit, '.', ',');
}else{
$real = ceil($number) * (-1);
$number = abs($number);
$decimal = number_format($number - $real, $decimal_digit, '.', ',');
}
$decimal = substr($decimal, strpos($decimal, '.') +1);
$unit_name[1] = 'thousand';
$unit_name[2] = 'million';
$unit_name[3] = 'billion';
$unit_name[4] = 'trillion';
$packet = array();
$number = strrev($real);
$packet = str_split($number,3);
for($i=0;$i<count($packet);$i++){
$tmp = strrev($packet[$i]);
$unit = $unit_name[$i];
if((int)$tmp == 0)
continue;
$tmp_res = '';
if(strlen($tmp) >= 2){
$tmp_proc = substr($tmp,-2);
switch($tmp_proc){
case '10':
$tmp_res = 'ten';
break;
case '11':
$tmp_res = 'eleven';
break;
case '12':
$tmp_res = 'twelve';
break;
case '13':
$tmp_res = 'thirteen';
break;
case '15':
$tmp_res = 'fifteen';
break;
case '20':
$tmp_res = 'twenty';
break;
case '30':
$tmp_res = 'thirty';
break;
case '40':
$tmp_res = 'forty';
break;
case '50':
$tmp_res = 'fifty';
break;
case '70':
$tmp_res = 'seventy';
break;
case '80':
$tmp_res = 'eighty';
break;
default:
$tmp_begin = substr($tmp_proc,0,1);
$tmp_end = substr($tmp_proc,1,1);
if($tmp_begin == '1')
$tmp_res = get_num_name($tmp_end).'teen';
elseif($tmp_begin == '0')
$tmp_res = get_num_name($tmp_end);
elseif($tmp_end == '0')
$tmp_res = get_num_name($tmp_begin).'ty';
else{
if($tmp_begin == '2')
$tmp_res = 'twenty';
elseif($tmp_begin == '3')
$tmp_res = 'thirty';
elseif($tmp_begin == '4')
$tmp_res = 'forty';
elseif($tmp_begin == '5')
$tmp_res = 'fifty';
elseif($tmp_begin == '6')
$tmp_res = 'sixty';
elseif($tmp_begin == '7')
$tmp_res = 'seventy';
elseif($tmp_begin == '8')
$tmp_res = 'eighty';
elseif($tmp_begin == '9')
$tmp_res = 'ninety';
$tmp_res = $tmp_res.' '.get_num_name($tmp_end);
}
break;
}
if(strlen($tmp) == 3){
$tmp_begin = substr($tmp,0,1);
$space = '';
if(substr($tmp_res,0,1) != ' ' && $tmp_res != '')
$space = ' ';
if($tmp_begin != 0){
if($tmp_begin != '0'){
if($tmp_res != '')
$tmp_res = 'and'.$space.$tmp_res;
}
$tmp_res = get_num_name($tmp_begin).' hundred'.$space.$tmp_res;
}
}
}else
$tmp_res = get_num_name($tmp);
$space = '';
if(substr($res,0,1) != ' ' && $res != '')
$space = ' ';
$res = $tmp_res.' '.$unit.$space.$res;
}
$space = '';
if(substr($res,-1) != ' ' && $res != '')
$space = ' ';
if($res)
$res .= $space.$real_name.(($real > 1 && $real_name != '')?'s':'');
if($decimal > 0)
$res .= ' '.num_to_words($decimal, '', 0, '').' '.$decimal_name.(($decimal > 1 && $decimal_name != '')?'s':'');
return ucfirst($res);
}
//////////// testing ////////////////
$str2num = 12;
while($str2num!=4){
$str = num_to_words($str2num, '', 0, '');
$str2num = strlen($str)-1;
echo $str . '=' . $str2num .'<br/>';
if ($str2num == 4)
echo 'four is magic';
}
////// Results /////////
Twelve =6
Six =3
Three =5
Five =4
four is magic
Perl - 130 chars
5.12.1 (130 chars) 121 123 132 136 140
# 1 2 3 4 5 6 7 8 9 100 11 12 13 14
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123
#u='4335443554366887798866555766'=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until/\D/
5.10.1 (134 chars) 125 127 136 140 144
# 1 2 3 4 5 6 7 8 9 100 11 12 13 14
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
#u='4335443554366887798866555766'=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,".\n"until/\D/
Change History:
20100714:2223 - reverted change at the attention of mobrule, but ($_%10&&$u[$_%10]) → (($_%=10)&&$u[$_]), which is the same # of chars, but I did it in case someone might see a way to improve it
20100714:0041 - split//,'...' → '...'=~/./g
20100714:0025 - ($_%10&&$u[$_%10]) → $u[$_%10]
20100713:2340 - while$_ → until/\D/ + removed unnecessary parentheses
20100713:xxxx - $=<>;chop; → $_=pop; - courtesy to mobrule
Note: I was tired of improving others' answers in comments, so now I'm being greedy and can just add my changes here :) This is a split off from Platinum Azure's answer - credit in part to Hobbs, mobrule, and Platinum Azure.
Shameless Perl with Number Words (329 characters)
Adapted fairly directly from P Daddy's C code, with some tweaks to p() to make it do the same thing using Perl primitives instead of C ones, and a mostly-rewritten mainloop. See his for an explanation. Newlines are all optional.
#t=(qw(zero one two three four five six sM eight nine
tL elM twelve NP 4P fifP 6P 7P 8O 9P twLQ NQ forQ fifQ
6Q 7Q 8y 9Q en evL thir eL tO ty 4SmagicT)," is ",".\n");
sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e;
print;length}$_=<>;chop;while($_-4){
$_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_;
p 35;p$_;p 36}p 34
Side note: it's too bad that perl print just returns true/false; if it returned a count it would save me 7 strokes.
Ruby, 141 chars:
n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? 'magic': n}.";n==s &&break}
while(true)
{
string a;
ReadLine(a)
WriteLine(4);
}

How do I display the binary representation of a float or double?

I'd like to display the binary (or hexadecimal) representation of a floating point number. I know how to convert by hand (using the method here), but I'm interested in seeing code samples that do the same.
Although I'm particularly interested in the C++ and Java solutions, I wonder if any languages make it particularly easy so I'm making this language agnostic. I'd love to see some solutions in other languages.
EDIT: I've gotten good coverage of C, C++, C#, and Java. Are there any alternative-language gurus out there who want to add to the list?
C/C++ is easy.
union ufloat {
float f;
unsigned u;
};
ufloat u1;
u1.f = 0.3f;
Then you just output u1.u.
Doubles just as easy.
union udouble {
double d;
unsigned long u;
}
because doubles are 64 bit.
Java is a bit easier: use Float.floatToRawIntBits() combined with Integer.toBinaryString() and Double.doubleToRawLongBits combined with Long.toBinaryString().
In C:
int fl = *(int*)&floatVar;
&floatVar would get the adress memory then (int*) would be a pointer to this adress memory, finally the * to get the value of the 4 bytes float in int.
Then you can printf the binary format or hex format.
Java: a google search finds this link on Sun's forums
specifically (I haven't tried this myself)
long binary = Double.doubleToLongBits(3.14159);
String strBinary = Long.toBinaryString(binary);
Apparently nobody cared to mention how trivial is to obtain hexadecimal exponent notation, so here it is:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
// C++11 manipulator
cout << 23.0f << " : " << std::hexfloat << 23.0f << endl;
// C equivalent solution
printf("23.0 in hexadecimal is: %A\n", 23.0f);
}
In .NET (including C#), you have BitConverter that accepts many types, allowing access to the raw binary; to get the hex, ToString("x2") is the most common option (perhaps wrapped in a utility method):
byte[] raw = BitConverter.GetBytes(123.45);
StringBuilder sb = new StringBuilder(raw.Length * 2);
foreach (byte b in raw)
{
sb.Append(b.ToString("x2"));
}
Console.WriteLine(sb);
Oddly, base-64 has a 1-line conversion (Convert.ToBase64String), but base-16 takes more effort. Unless you reference Microsoft.VisualBasic, in which case:
long tmp = BitConverter.DoubleToInt64Bits(123.45);
string hex = Microsoft.VisualBasic.Conversion.Hex(tmp);
I did it this way:
/*
#(#)File: $RCSfile: dumpdblflt.c,v $
#(#)Version: $Revision: 1.1 $
#(#)Last changed: $Date: 2007/09/05 22:23:33 $
#(#)Purpose: Print C double and float data in bytes etc.
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 2007
#(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
#include <stdio.h>
#include "imageprt.h"
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_dumpdblflt_c[];
const char jlss_id_dumpdblflt_c[] = "#(#)$Id: dumpdblflt.c,v 1.1 2007/09/05 22:23:33 jleffler Exp $";
#endif /* lint */
union u_double
{
double dbl;
char data[sizeof(double)];
};
union u_float
{
float flt;
char data[sizeof(float)];
};
static void dump_float(union u_float f)
{
int exp;
long mant;
printf("32-bit float: sign: %d, ", (f.data[0] & 0x80) >> 7);
exp = ((f.data[0] & 0x7F) << 1) | ((f.data[1] & 0x80) >> 7);
printf("expt: %4d (unbiassed %5d), ", exp, exp - 127);
mant = ((((f.data[1] & 0x7F) << 8) | (f.data[2] & 0xFF)) << 8) | (f.data[3] & 0xFF);
printf("mant: %16ld (0x%06lX)\n", mant, mant);
}
static void dump_double(union u_double d)
{
int exp;
long long mant;
printf("64-bit float: sign: %d, ", (d.data[0] & 0x80) >> 7);
exp = ((d.data[0] & 0x7F) << 4) | ((d.data[1] & 0xF0) >> 4);
printf("expt: %4d (unbiassed %5d), ", exp, exp - 1023);
mant = ((((d.data[1] & 0x0F) << 8) | (d.data[2] & 0xFF)) << 8) |
(d.data[3] & 0xFF);
mant = (mant << 32) | ((((((d.data[4] & 0xFF) << 8) |
(d.data[5] & 0xFF)) << 8) | (d.data[6] & 0xFF)) << 8) |
(d.data[7] & 0xFF);
printf("mant: %16lld (0x%013llX)\n", mant, mant);
}
static void print_value(double v)
{
union u_double d;
union u_float f;
f.flt = v;
d.dbl = v;
printf("SPARC: float/double of %g\n", v);
image_print(stdout, 0, f.data, sizeof(f.data));
image_print(stdout, 0, d.data, sizeof(d.data));
dump_float(f);
dump_double(d);
}
int main(void)
{
print_value(+1.0);
print_value(+2.0);
print_value(+3.0);
print_value( 0.0);
print_value(-3.0);
print_value(+3.1415926535897932);
print_value(+1e126);
return(0);
}
Running on a SUN UltraSPARC, I got:
SPARC: float/double of 1
0x0000: 3F 80 00 00 ?...
0x0000: 3F F0 00 00 00 00 00 00 ?.......
32-bit float: sign: 0, expt: 127 (unbiassed 0), mant: 0 (0x000000)
64-bit float: sign: 0, expt: 1023 (unbiassed 0), mant: 0 (0x0000000000000)
SPARC: float/double of 2
0x0000: 40 00 00 00 #...
0x0000: 40 00 00 00 00 00 00 00 #.......
32-bit float: sign: 0, expt: 128 (unbiassed 1), mant: 0 (0x000000)
64-bit float: sign: 0, expt: 1024 (unbiassed 1), mant: 0 (0x0000000000000)
SPARC: float/double of 3
0x0000: 40 40 00 00 ##..
0x0000: 40 08 00 00 00 00 00 00 #.......
32-bit float: sign: 0, expt: 128 (unbiassed 1), mant: 4194304 (0x400000)
64-bit float: sign: 0, expt: 1024 (unbiassed 1), mant: 2251799813685248 (0x8000000000000)
SPARC: float/double of 0
0x0000: 00 00 00 00 ....
0x0000: 00 00 00 00 00 00 00 00 ........
32-bit float: sign: 0, expt: 0 (unbiassed -127), mant: 0 (0x000000)
64-bit float: sign: 0, expt: 0 (unbiassed -1023), mant: 0 (0x0000000000000)
SPARC: float/double of -3
0x0000: C0 40 00 00 .#..
0x0000: C0 08 00 00 00 00 00 00 ........
32-bit float: sign: 1, expt: 128 (unbiassed 1), mant: 4194304 (0x400000)
64-bit float: sign: 1, expt: 1024 (unbiassed 1), mant: 2251799813685248 (0x8000000000000)
SPARC: float/double of 3.14159
0x0000: 40 49 0F DB #I..
0x0000: 40 09 21 FB 54 44 2D 18 #.!.TD-.
32-bit float: sign: 0, expt: 128 (unbiassed 1), mant: 4788187 (0x490FDB)
64-bit float: sign: 0, expt: 1024 (unbiassed 1), mant: 2570638124657944 (0x921FB54442D18)
SPARC: float/double of 1e+126
0x0000: 7F 80 00 00 ....
0x0000: 5A 17 A2 EC C4 14 A0 3F Z......?
32-bit float: sign: 0, expt: 255 (unbiassed 128), mant: 0 (0x000000)
64-bit float: sign: 0, expt: 1441 (unbiassed 418), mant: -1005281217 (0xFFFFFFFFC414A03F)
Well both the Float and Double class (in Java) have a toHexString('float') method so pretty much this would do for hex conversion
Double.toHexString(42344);
Float.toHexString(42344);
Easy as pie!
I had to think about posting here for a while because this might inspire fellow coders to do evil things with C. I decided to post it anyway but just remember: do not write this kind of code to any serious application without proper documentation and even then think thrice.
With the disclaimer aside, here we go.
First write a function for printing for instance a long unsigned variable in binary format:
void printbin(unsigned long x, int n)
{
if (--n) printbin(x>>1, n);
putchar("01"[x&1]);
}
Unfortunately we can't directly use this function to print our float variable so we'll have to hack a little. The hack probably looks familiar to everyone who have read about Carmack's Inverse Square Root trick for Quake. The idea is set a value for our float variable and then get the same bit mask for our long integer variable. So we take the memory address of f, convert it to a long* value and use that pointer to get the bit mask of f as a long unsigned. If you were to print this value as long unsigned, the result would be a mess, but the bits are the same as in the original float value so it doesn't really matter.
int main(void)
{
long unsigned lu;
float f = -1.1f;
lu = *(long*)&f;
printbin(lu, 32);
printf("\n");
return 0;
}
If you think this syntax is awful, you're right.
In Haskell, there is no internal representation of floating points accessible. But you can do binary serialiazation from many formats, including Float and Double. The following solution is generic to any type that has instance of Data.Binary supports:
module BinarySerial where
import Data.Bits
import Data.Binary
import qualified Data.ByteString.Lazy as B
elemToBits :: (Bits a) => a -> [Bool]
elemToBits a = map (testBit a) [0..7]
listToBits :: (Bits a) => [a] -> [Bool]
listToBits a = reverse $ concat $ map elemToBits a
rawBits :: (Binary a) => a -> [Bool]
rawBits a = listToBits $ B.unpack $ encode a
Conversion can be done with rawBits:
rawBits (3.14::Float)
But, if you need to access the float value this way, you are probably doing something wrong. The real question might be How to access exponent and significand of a floating-point number? The answers are exponent and significand from Prelude:
significand 3.14
0.785
exponent 3.14
2
Python:
Code:
import struct
def float2bin(number, hexdecimal=False, single=False):
bytes = struct.pack('>f' if single else '>d', number)
func, length = (hex, 2) if hexdecimal else (bin, 8)
byte2bin = lambda byte: func(ord(byte))[2:].rjust(length, '0')
return ''.join(map(byte2bin, bytes))
Sample:
>>> float2bin(1.0)
'0011111111110000000000000000000000000000000000000000000000000000'
>>> float2bin(-1.0)
'1011111111110000000000000000000000000000000000000000000000000000'
>>> float2bin(1.0, True)
'3ff0000000000000'
>>> float2bin(1.0, True, True)
'3f800000'
>>> float2bin(-1.0, True)
'bff0000000000000'
You can easy convert float variable to int variable (or double to long) using such code in C#:
float f = ...;
unsafe
{
int i = *(int*)&f;
}
For future reference, C++ 2a introduce a new function template bit_cast that does the job.
template< class To, class From >
constexpr To bit_cast(const From& from) noexcept;
We can simply call,
float f = 3.14;
std::bit_cast<int>(f);
For more details, see https://en.cppreference.com/w/cpp/numeric/bit_cast
In C++ you can show the binary representation it in this way:
template <class T>
std::bitset<sizeof(T)*8> binary_representation(const T& f)
{
typedef unsigned long TempType;
assert(sizeof(T)<=sizeof(TempType));
return std::bitset<sizeof(T)*8>(*(reinterpret_cast<const TempType*>(&f)));
}
the limit here is due the fact that bitset longer parameter is an unsigned long,
so it works up to float, you can use something else than bitset and the extend
that assert.
BTW, cletus suggestion fails in the sense that you need an "unsingned long long" to cover a double, anyway you need something that shows the binary (1 or 0) representation.