Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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 -> )
share|improve this question

11 Answers 11

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);}
share|improve this answer
    
shoot, there's a string literal in the printf. fixing later –  Martin Büttner Jul 25 at 22:19
    
putchar() - and its 4 bytes shorter too! –  DigitalTrauma Jul 25 at 22:54
1  
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 at 23:18
1  
@DigitalTrauma yeah I know, I just didn't think of it right away for some reason and had to leave really quickly then –  Martin Büttner Jul 25 at 23:58
1  
a[]={8,0,31,2,3,4,61,5,9,7};main(d){for(;d=getchar();)putchar(d>47&d<58‌​?a[d-4‌​8]+33:d);} –  millinon Jul 26 at 0:11

Perl - 74 57 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(<>)'
share|improve this answer
    
Are you sure that isn't a string literal? !@#$%^&*() sure looks like one. –  isaacg Jul 25 at 23:01
    
@isaacg I didn't read the question closely enough and I think you're right. I updated with another solution. –  chilemagic Jul 25 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 at 13:36
    
@manatwork thanks! nice work! I updated the answer. Also you can take the parenthesis out of chr(...). –  chilemagic Jul 29 at 14:17
1  
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 at 8:08

JavaScript (ES6) - 79 76 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.

share|improve this answer
    
Wouldn't you have to iterate over it? The input is not guaranteed to be one digit... –  soktinpk Jul 31 at 0:00
    
Also, this doesn't satisfy the rule characters which aren't digits should be left alone. –  soktinpk Jul 31 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 at 0:29
    
@soktinpk - fixed now - but it cost me 11 characters. Curse you! :P –  Alconja Jul 31 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.

share|improve this answer

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 {
  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
}
share|improve this answer

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"(!@#$%^&*("))))
share|improve this answer

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]))
share|improve this answer
2  
Looks like you used a string literal. –  isaacg Jul 25 at 23:39
    
@isaacg Updated, sorry. –  soktinpk Jul 25 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^ ^                 <
share|improve this answer

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"

"!!&&%*#@^"

share|improve this answer

CJam - 32

qA,s26063649909601297730 95b:cer

Try it at http://cjam.aditsu.net/

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

share|improve this answer

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
share|improve this answer
    
d=')!@#$%^&*(' is way shorter, though it uses string literals. your original answer does too though –  pseudonym117 Aug 1 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. –  Batman Aug 1 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 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. –  Batman Aug 1 at 18:01
    
ah. still, combining the 2 lines into 1 would work identically. –  pseudonym117 Aug 1 at 18:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.