6
\$\begingroup\$

In the fewest bytes, generate the dictionary of keypresses for any letter (as described in https://code.google.com/codejam/contest/351101/dashboard#s=p2)

In Python, the dictionary literal itself:

{'a':2,'c':222,'b':22,'e':33,'d':3,'g':4,'f':333,'i':444,'h':44,'k':55,'j':5,'m':6,'l':555,'o':666,'n':66,'q':77,'p':7,'s':7777,'r':777,'u':88,'t':8,'w':9,'v':888,'y':999,'x':99,'z':9999}

is 187 bytes so it needs to be less than that. (The values can be strings or ints, ie you can have 'a':'2' or 'a':2 it's up to you)

NOTE: This is not asking you to solve the referenced GCJ problem, it's just asking you to generate a particular dictionary which is related to that problem.

EDIT: You may solve this in any language which has a dictionary-like type (ie hashmap, associative array etc.)

\$\endgroup\$
8
  • \$\begingroup\$ Do we have to solve this in Python, or can we use any language to generate and output the dictionary literal? \$\endgroup\$ Apr 11, 2014 at 19:48
  • \$\begingroup\$ I guess any language. Let me fix that \$\endgroup\$
    – dspyz
    Apr 11, 2014 at 19:49
  • 1
    \$\begingroup\$ Also, looks like the GCJ problem itself has been asked here before. \$\endgroup\$ Apr 11, 2014 at 19:51
  • \$\begingroup\$ Huh, I should have checked that first. I posted this because we were talking about how to generate this dictionary (in Python) on #gcj on Freenode \$\endgroup\$
    – dspyz
    Apr 11, 2014 at 19:53
  • \$\begingroup\$ Order doesn't matter? \$\endgroup\$
    – kukac67
    Apr 11, 2014 at 20:22

11 Answers 11

6
\$\begingroup\$

perl, 49 48 bytes

Using a different algorithm than my previous answer, we can lose another 12 bytes. The basic idea is that you usually just add the digit from the last letter's solution over again. We handle the other cases (detected by a short regex) by starting with a single instance of the last digit + 1.

{map{$d++,$t=""if/[dgjmptw]/;$_,$t.=$d||=2}a..z}

With output:

ski@anito:~/src$ perl -MData::Dumper  -e '$Data::Dumper::Sortkeys=1; $d=2;print Dumper {map{$d++,$t=""if/[dgjmptw]/;$_,$t.=$d}a..z}'
$VAR1 = {
      'a' => '2',
      'b' => '22',
      'c' => '222',
      'd' => '3',
      'e' => '33',
      'f' => '333',
      'g' => '4',
      'h' => '44',
      'i' => '444',
      'j' => '5',
      'k' => '55',
      'l' => '555',
      'm' => '6',
      'n' => '66',
      'o' => '666',
      'p' => '7',
      'q' => '77',
      'r' => '777',
      's' => '7777',
      't' => '8',
      'u' => '88',
      'v' => '888',
      'w' => '9',
      'x' => '99',
      'y' => '999',
      'z' => '9999'
};
\$\endgroup\$
1
  • \$\begingroup\$ Woo! Suck it J and Golfscript. Perl 4 eva! ;-) \$\endgroup\$ Jun 1, 2014 at 17:17
3
\$\begingroup\$

Golfscript, 68 characters

"{'"26,{.[.",'"''if\97+"':"]''+\..11-
7/.0>*-.3/2[+]\3%)@18=+*}/"9}"

What's this, you say? It outputs the correct Python dict literal:

{'a':2,'b':22,'c':222,'d':3,'e':33,'f':333,'g':4,'h':44,'i':444,'j':5,'k':55,'l':555,'m':6,'n':66,'o':666,'p':7,'q':77,'r':777,'s':7777,'t':8,'u':88,'v':888,'w':9,'x':99,'y':999,'z':9999}

That is,

$ echo print `ruby golfscript.rb phonetyp.gs` | python
{'a': 2, 'c': 222, 'b': 22, 'e': 33, 'd': 3, 'g': 4, 'f': 333, 'i': 444, 'h': 44, 'k': 55, 'j': 5, 'm': 6, 'l': 555, 'o': 666, 'n': 66, 'q': 77, 'p': 7, 's': 7777, 'r': 777, 'u': 88, 't': 8, 'w': 9, 'v': 888, 'y': 999, 'x': 99, 'z': 9999}
\$\endgroup\$
3
\$\begingroup\$

Python (83)(87)

c,d=97,{}
for i in range(2,10):
 for j in range(1,4+(i>6)*i%2):d[chr(c)],c=j*str(i),c+1

The dictionary is stored in d. The condition check (i>6)*i%2 saves two chars from (i in[7,9]).

Edit:

c=97;d={}
for i in range(8):
 for j in range(1,4+(i|2>6)):d[chr(c)]=j*str(i+2);c+=1

Shaved 4 characters. With i shifted down by 2, we recognize the special cases of 7 and 9 by checking if i is 5 or 7 using i|2>6.

\$\endgroup\$
2
  • \$\begingroup\$ (6<i<10) saves another character. \$\endgroup\$
    – isaacg
    Apr 11, 2014 at 22:34
  • 1
    \$\begingroup\$ @isaacg but it includes 8... \$\endgroup\$ Apr 12, 2014 at 12:18
2
\$\begingroup\$

Python, 86 characters

Alternate Python solution:

d={}
for a in range(26):n=a-max(0,(a-11)/7);d[chr(a+97)]=`n/3+2`*(n%3+1+(a in(18,25)))
\$\endgroup\$
1
  • \$\begingroup\$ For this range max(0,(a-11)/7) = max(0,a-11)/7 = a/18-a/25. You can squeeze 2 or even 6 more bytes ;) \$\endgroup\$
    – core1024
    May 19, 2014 at 14:09
1
\$\begingroup\$

J - 57 char

The closest analogue to the dictionary datatype in J is a table of boxes: each row is an entry, containing the key on the left and the data on the right. It's not really unordered, but whenever you need a dictionary type of record, you would use something like this.

_2]\;n(;&.><\)/@|:/.n,.~u:97+i.#n=.,":"0(#~3+e.&7 9)2+i.8

n is the string '22233344455566677778889999', which we create by taking the list 2 3 4 5 6 7 8 9 and taking three of 4 of each element, depending on whether the element is 7 or 9. Then we just convert each item to a string and run them together into a single string.

Then we make the alphabet, attach the digits to the alphabet with ,.~, and then group them by the digits (this is /. at work). Within each group, we pair off the letter with the corresponding prefix of the string of same digits.

Finally, we run things together: ; to take off the effects of the earlier grouping and _2]\ to put it into the proper table shape.

   _2]\;n(;&.><\)/@|:/.n,.~u:97+i.#n=.,":"0(#~3+e.&7 9)2+i.8
+-+----+
|a|2   |
+-+----+
|b|22  |
+-+----+
|c|222 |
+-+----+
|d|3   |
+-+----+
|e|33  |
+-+----+
|f|333 |
+-+----+
|g|4   |
+-+----+
|h|44  |
+-+----+
|i|444 |
+-+----+
|j|5   |
+-+----+
|k|55  |
+-+----+
|l|555 |
+-+----+
|m|6   |
+-+----+
|n|66  |
+-+----+
|o|666 |
+-+----+
|p|7   |
+-+----+
|q|77  |
+-+----+
|r|777 |
+-+----+
|s|7777|
+-+----+
|t|8   |
+-+----+
|u|88  |
+-+----+
|v|888 |
+-+----+
|w|9   |
+-+----+
|x|99  |
+-+----+
|y|999 |
+-+----+
|z|9999|
+-+----+
\$\endgroup\$
1
\$\begingroup\$

perl, 61 bytes

Examine the mod3 and div3 of a counter $t to determine the base digit and number of repetitions. Handle the special cases of s and z separately.

$t=5;{map{$b=++$t%3+1;$b=4,--$t if/s|z/;$_,int($t/3)x$b}a..z}

With string output:

perl -MData::Dumper -e '$Data::Dumper::Sortkeys=1; $t=5;print Dumper {map{$b=++$t%3+1;$b=4,--$t if/s|z/;$_,int($t/3)x$b}a..z}' 
$VAR1 = {
      'a' => '2',
      'b' => '22',
      'c' => '222',
      'd' => '3',
      'e' => '33',
      'f' => '333',
      'g' => '4',
      'h' => '44',
      'i' => '444',
      'j' => '5',
      'k' => '55',
      'l' => '555',
      'm' => '6',
      'n' => '66',
      'o' => '666',
      'p' => '7',
      'q' => '77',
      'r' => '777',
      's' => '7777',
      't' => '8',
      'u' => '88',
      'v' => '888',
      'w' => '9',
      'x' => '99',
      'y' => '999',
      'z' => '9999'
    };

And here's a more readable version of the code:

{
  map {
    my $reps = (++$pos % 3) + 1;
    if($_ =~ /s|z/) {
      --$pos;
      $reps=4;
    }
    my $digit = int( $pos/3 );
    $_ => $digit x $reps
  } ('a'..'z')
}

We start with $pos = 5 so that int(++$pos/3) starts off at 2.

We handle the case of s and z separately since they are the only exceptions to the modulo 3 rule.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES5) 88 86 85 bytes

for(o={},a=c=2,b=96;a-10;a=a<(c%9%7?b:1e3)?a+[c]:++c)o[String.fromCharCode(++b)]=+a;o

Result:

{"a":2,"b":22,"c":222,"d":3,"e":33,"f":333,"g":4,"h":44,"i":444,"j":5,"k":55,"l":555,"m":6,"n":66,"o":666,"p":7,"q":77,"r":777,"s":7777,"t":8,"u":88,"v":888,"w":9,"x":99,"y":999,"z":9999}

If mixed types are allowed, it can be reduced by 1 byte.

86 84 bytes:

for(o={},a=c=2,b=96;a-10;a=a<(c%9%7?b:1e3)?a+[c]:++c)o[String.fromCharCode(++b)]=a;o

Result:

{"a":2,"b":"22","c":"222","d":3,"e":"33","f":"333","g":4,"h":"44","i":"444","j":5,"k":"55","l":"555","m":6,"n":"66","o":"666","p":7,"q":"77","r":"777","s":"7777","t":8,"u":"88","v":"888","w":9,"x":"99","y":"999","z":"9999"}
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 168

This is the longest answer here... I'm sure there's a better way to do this.

(k=#2[[1]]+1;Append[{},{#->StringJoin@ConstantArray[ToString@k,#2]}]&~MapIndexed~#)&~MapIndexed~Characters@{"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}~Flatten~3

Output:

{"a" -> "2", "b" -> "22", "c" -> "222", "d" -> "3", "e" -> "33", 
"f" -> "333", "g" -> "4", "h" -> "44", "i" -> "444", "j" -> "5", 
"k" -> "55", "l" -> "555", "m" -> "6", "n" -> "66", "o" -> "666", 
"p" -> "7", "q" -> "77", "r" -> "777", "s" -> "7777", "t" -> "8", 
"u" -> "88", "v" -> "888", "w" -> "9", "x" -> "99", "y" -> "999", 
"z" -> "9999"}
\$\endgroup\$
0
\$\begingroup\$

Bash + coreutils, 91 bytes

p="printf %s\n"
paste <($p {a..z}) <($p {2..9} {22..99..11} {222..999..111} 7777 9999|sort)

Generates a tab-delimited table, which is a natural structure for a shell script - not sure if that meets the specs or not:

a   2
b   22
c   222
d   3
...
r   777
s   7777
t   8
u   88
v   888
w   9
x   99
y   999
z   9999

Pure Bash, 137 bytes

Not very good.

declare -A a
b=({X..z})
for n in {9..33};do
c=${b[n]}
((n>26?n--:n))
printf -vk %$[n%3+1]s
a[$c]=${k// /$[n/3-1]}
done
a[s]+=7
a[z]=9999

This populates a bash associative array.

Crudely display it as follows:

$ for c in ${!a[@]}; do echo -n $c:${a[$c]},;done; echo
a:2,b:22,c:222,d:3,e:33,f:333,g:4,h:44,i:444,j:5,k:55,l:555,m:6,n:66,o:666,p:7,q:77,r:777,s:7777,t:8,u:88,v:888,w:9,x:99,y:999,z:9999,
$ 
\$\endgroup\$
0
\$\begingroup\$

Python 2 (97)

I used a single dictionary comprehension:

{zip(*[(chr(i)for i in range(65,91))]*3)[i][k]:str(i+2)*(k+1)for k in range(3)for i in range(8)}

Unfortunately it's missing the z because on number 9 there are 4 letters.

\$\endgroup\$
2
  • \$\begingroup\$ You could manually add the z for a few more characters. Also remove the space between the many ...) for... to ...)for... \$\endgroup\$
    – user80551
    Apr 12, 2014 at 10:20
  • \$\begingroup\$ Y is also missing \$\endgroup\$
    – user80551
    Apr 12, 2014 at 10:21
0
\$\begingroup\$

Clojure, 91 bytes

(zipmap(map char(range 97 123))(for[i(range 2 10)r(range 1(get{7 5 9 5}i 4))](repeat r i)))

for is ideal for generating these kinds of sequences. Output looks like this:

{\a (2), \b (2 2), \c (2 2 2), \d (3), ...
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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