# Convert numbers to symbols without string or char literals

Read infinitely from stdin, and convert every number to the corresponding symbol on a US qwerty keyboard.

No string or character literals anywhere are permitted.

E.g. if the input is 117758326, the output is !!&&%*#@^.

Letters and symbols that aren't on numbers are left alone; 11g2;;'1g2311hh21930 turns into !!g@;;'!g@#!!hh@!(#)

Shortest code, in bytes, wins.

For those who don't have a US qwerty keyboard, use the following as a guide:

1 -> !
2 -> @
3 -> #
4 -> $5 -> % 6 -> ^ 7 -> & 8 -> * 9 -> ( 0 -> )  ## 12 Answers ## C, 90 bytes The line between a character and an integer literal is a very fine one in C. a[]={8,0,31,2,3,4,61,5,9,7};main(d){for(;~(d=getchar());)putchar(d>47&d<58?a[d-48]+33:d);}  • shoot, there's a string literal in the printf. fixing later – Martin Ender Jul 25 '14 at 22:19 • putchar() - and its 4 bytes shorter too! – Digital Trauma Jul 25 '14 at 22:54 • this is 92 a[]={41,33,64,35,36,37,94,39,42,40};main(d){for(;d=getchar();)putchar(d>47&d<58?a[d-48]:d);} – bebe Jul 25 '14 at 23:18 • @DigitalTrauma yeah I know, I just didn't think of it right away for some reason and had to leave really quickly then – Martin Ender Jul 25 '14 at 23:58 • a[]={8,0,31,2,3,4,61,5,9,7};main(d){for(;d=getchar();)putchar(d>47&d<58‌​?a[d-48]+33:d);} – millinon Jul 26 '14 at 0:11 ## Perl - 7457 42 Update thanks to core1024's comment: s/\d/chr 33+(8,0,31,2..4,61,5,9,7)[$&]/eg


Run with:

perl -p program_name.pl


Update thanks to manatwork's comment:

say s/\d/chr@{[8,0,31,2,3,4,61,5,9,7]}[$&]+33/erg while<>  Test with: perl -E 'say s/\d/chr@{[8,0,31,2,3,4,61,5,9,7]}[$&]+33/erg while<>'


Old attempts:

say s/[1234567890]/chr qw(41 33 64 35 36 37 94 38 42 40)[$&]/erg while(<>)  Using qw counts as a string literal though. Test: perl -E 'say s/[1234567890]/chr qw(41 33 64 35 36 37 94 38 42 40)[$&]/erg while(<>)'


Another way: Perl 40 - I think this counts as a string literal as well.

say tr/1234567890/!@#$%^&*()/r while(<>)  Test with: perl -E 'say tr/1234567890/!@#$%^&*()/r while(<>)'

• Are you sure that isn't a string literal? !@#$%^&*() sure looks like one. – isaacg Jul 25 '14 at 23:01 • @isaacg I didn't read the question closely enough and I think you're right. I updated with another solution. – hmatt1 Jul 25 '14 at 23:45 • As documentation describes qw// as “quote a list of words”, in my interpretation there you have 10 string literals. So I suggest to change it into array of integers (@{[41,33,…]} or something better) (no change in code size); leave off the parenthesis around the statement modifier's expression (2 characters shorter); subtract 33 from all character codes and add it separately (3 characters shorter); replace character class with \d wildcard (10 characters shorter): say s/\d/chr(@{[8,0,31,2,3,4,61,5,9,7]}[$&]+33)/erg while<>. – manatwork Jul 29 '14 at 13:36
• @manatwork thanks! nice work! I updated the answer. Also you can take the parenthesis out of chr(...). – hmatt1 Jul 29 '14 at 14:17
• You can use the -p flag to drop the while, say and the r RegEx modifier from your code. You can also save more bytes by using 33+(31,2..4,61)[] instead of @{[31,2,3,4,61]}[]+33. – core1024 Jul 31 '14 at 8:08

# JavaScript (ES6) - 7976 87

Edit - bloated out by 11 chars after it was pointed out that it failed the "non-numbers are left alone" rule (thanks @soktinpk)

Warning - you'll need to reload your browser after you run it since it's following the "Read infinitely from stdin" bit...

(f=x=>f(alert(+(p=prompt())+1?String.fromCharCode([8,0,31,2,3,4,61,5,9,7][p]+33):p)))()


Note that I've interpreted prompt as stdin & alert as stdout

Tested in Firefox console.

• Wouldn't you have to iterate over it? The input is not guaranteed to be one digit... – soktinpk Jul 31 '14 at 0:00
• Also, this doesn't satisfy the rule characters which aren't digits should be left alone. – soktinpk Jul 31 '14 at 0:07
• @soktinpk - on your first point, it loops indefinitely by recursively calling itself (it's an interpretation of how to indefinitely read from stdin in javascript... the implication of the question is that it should process each character as it comes in, which is effectively what I'm doing, via a prompt). Your second point is spot on though, I missed that... will have to revisit the code... – Alconja Jul 31 '14 at 0:29
• @soktinpk - fixed now - but it cost me 11 characters. Curse you! :P – Alconja Jul 31 '14 at 0:48

# Pyth, 43

W1sm?C+33@[8Z31 2 3 4 61 5tT7)vd}Cdr48 58dw


Uses 33+table lookup, instead of straight table lookup. No translate function here, just a normal map. Note that Z=0 and tT=9.

## Scala, 106 bytes

def f{println(readLine.map{c=>try{(Seq(8,0,31,2,3,4,61,5,9,7)(c.toInt-48)+33).toChar}catch{case _=>c}});f}


Pretty-printed:

def f {
try {
(Seq(8,0,31,2,3,4,61,5,9,7)(c.toInt - 48) + 33).toChar
} catch {
case _ => c
}
})
f
}


# pyg-i (68)

Here is a solution in pyg-i, a fork of pyg I created:

while 1:P(Ip().t(dict(Z(R(48,58),(41,33,64,35,36,37,94,38,42,40)))))


The python 3 equivalent would be this:

while 1:print(input().translate(dict(zip(range(48,58),(41,33,64,35,36,37,94,38,42,40)))))


Or, with a little cheating, it can be done in 50 bytes. Note that this is a bytes literal, not a string literal:

while 1:P(Ip().t(dict(Z(R(48,58),b"(!@#$%^&*("))))  # CoffeeScript (70) Update: This may be seen as reading between the lines, but while strings and characters aren't allowed, regexs are. (I just converted the regex to a string). alert prompt().replace /\d/g, (t)->([]+/!@#$%^&*()/)[1...-1][(+t+9)%10]


Or (for infinite)

loop alert prompt().replace /\d/g, (t)->([]+/!@#$%^&*()/)[1...-1][(+t+9)%10]  The normal version (in case regex isn't allowed): alert prompt().replace(/\d/g, (t) ->String.fromCharCode(([]+4133643536+3794384240).match(/\d{2}/g)[t]))  Test it out here. But, according to the problem statement, Read infinitely from stdin That will probably hang your browser eventually, but here it is (just prepend loop, extra 5 bytes, to the code): loop alert prompt().replace(/\d/g, (t) ->String.fromCharCode(([]+4133643536+3794384240).match(/\d{2}/g)[t]))  • Looks like you used a string literal. – isaacg Jul 25 '14 at 23:39 • @isaacg Updated, sorry. – soktinpk Jul 25 '14 at 23:54 # Befunge 98 - 119 bytes This is also with the STRN fingerprint, that allows "S" to stand for a convert integer to string instruction. v>0 NRTS 4( >&S v >$a,v
5 )!@#$%^&*( >:1 w1 v 7^ p< ^,g1--3*77< >*1-:30p80^ ^ <  Haskell, 89 f 50=64 f 54=94 f 55=38 f 56=42 f 57=40 f 48=41 f x|x<48||x>57=x|0<1=x-16 g=map$chr.f.ord


tests:

Prelude> g "11g2;;'1g2311hh21930"

"!!g@;;'!g@#!!hh@!(#)"

Prelude> g "117758326"

"!!&&%*#@^"

# CJam - 32

qA,s26063649909601297730 95b:cer


Explanation:

q reads the whole input
A, creates the array [0 1 ... 9] (A=10)
s converts to string, obtaining "0123456789"
95b converts the previous big number to an array of base-95 digits, which are the ASCII codes of the 10 symbols we want
:c converts the ASCII codes to characters, obtaining the string ")!@#$%^&*(" er transliterates "0123456789" to ")!@#$%^&*(" in the input string

# tcl, 156

proc x n {format %c $n} while 1 {puts [string map "1 [x 33] 2 [x 64] 3 [x 35] 4 [x 36] 5 [x 37] 6 [x 94] 7 [x 38] 8 [x 36] 9 [x 40] 0 [x 41]" [gets stdin]]}  PYTHON: 166 86 Not better than the current answers, but the shortest Python solution I can think of as of yet. (thanks to pseudonym117 for helping me shorten this significantly) def g(s): d=')!@#$%^&*('
g=''
for c in s:
try:g+=d[int(c)]
except:g+=c
yield g

• d=')!@#\$%^&*(' is way shorter, though it uses string literals. your original answer does too though – pseudonym117 Aug 1 '14 at 17:58
• Whoops, definitely grazed right over that limitation. I'll leave this one up anyway, and take your suggestion which for some reason I totally didn't think of. – RageCage Aug 1 '14 at 17:59
• also w=int(c) seems to not do anything at all, and g+=d[c] would need to be changed to g+=d[int(c)] – pseudonym117 Aug 1 '14 at 18:00
• w=int(c) is to catch anything that isn't a number that may be in the string. int() raises an exception if it isn't passed a proper integer. – RageCage Aug 1 '14 at 18:01
• ah. still, combining the 2 lines into 1 would work identically. – pseudonym117 Aug 1 '14 at 18:03