11
\$\begingroup\$

Assume an simple keyboard with this layout:

1 2 3 4 5 6 7 8 9 0
A B C D E F G H I J
K L M N O P Q R S T
U V W X Y Z . , ? !

Peter's keyboard pattern can be generated by starting at the top left of the keyboard, and displays the first three characters and a newline. It shifts over one character and displays the second, third, and fourth key. Once it reaches the end of a row it continues at the end of the next row and goes backwards, until it reaches the start of that row and then goes forward on the next row, and so on until it reaches the beginning of the last row.

This is Peter's keyboard pattern:

123
234
345
456
567
678
789
890
90J
0JI
JIH
IHG
HGF
GFE
FED
EDC
DCB
CBA
BAK
AKL
KLM
LMN
MNO
NOP
OPQ
PQR
QRS
RST
ST!
T!?
!?,
?,.
,.Z
.ZY
ZYX
YXW
XWV
WVU

Write a program which accepts no input and displays Peter's keyboard pattern. The program must be smaller than 152 bytes, i.e. the size of the string it outputs.

This is code golf, so the shortest solution wins.

\$\endgroup\$
4
  • \$\begingroup\$ Even in Golfscript I'm struggling to come up with a shorter way of generating the 40-character base string. \$\endgroup\$ Commented Dec 2, 2011 at 8:18
  • \$\begingroup\$ @PeterTaylor I was expecting somebody to use some sort of list comprehension, like [1..9 0 J..A K..T ! ? , . Z..U]. \$\endgroup\$ Commented Dec 3, 2011 at 17:02
  • \$\begingroup\$ You can use echo {1..9} "0" {J..A} {K..T} '!?,.' {Z..U}|sed 's/ //g' in bash, but need already 13 chars to append a sed-command, to remove blanks. This makes 57 chars, and no triple has been build so far. With sed's hold-command, it should be possible, but in 6 chars, to beat the perl-solution? \$\endgroup\$ Commented Dec 9, 2011 at 0:38
  • 6
    \$\begingroup\$ The 152 byte limit seems unnecessary--hardcoding the output with no compression whatsoever is bad golfing anyways. It could also potentially bar languages such as brainf**k, where large programs are almost always the occurance but there still could be some clever golfing going on. \$\endgroup\$
    – Zwei
    Commented Oct 3, 2016 at 22:36

29 Answers 29

7
\$\begingroup\$

Perl, 63 chars

say for"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"=~/(?=(...))/g

This solution uses the say function (available since Perl 5.10.0 with the -E switch, or with use 5.010). Without it, the best I can do is 67 chars (and an extra newline at the end of the output):

print"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"=~/(?=(...))/g,$,=$/

Earlier 65-char solution:

s//1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU/;s!(?=(...))!say$1!eg

Replacing say$1 with print$1.$/ lets the code run on older perls, at the cost of 5 extra characters.

\$\endgroup\$
2
  • \$\begingroup\$ you beat me for few characters. +1. \$\endgroup\$
    – Toto
    Commented Dec 2, 2011 at 13:20
  • 2
    \$\begingroup\$ Go for the 63-char solution directly. meta discussion \$\endgroup\$
    – J B
    Commented Dec 2, 2011 at 15:20
7
\$\begingroup\$

J, 66 62 45 characters

Turns out I was being too clever by half.

3]\'1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'

is all I needed all along.

Previously:

_2}.|:>(];1&|.;2&|.)'1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'

and:

38 3$($:@}.,~3$])^:(3<#)'1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'
\$\endgroup\$
6
\$\begingroup\$

APL, 43 characters

⍪3,/(1⌽⎕D),(⌽10↑⎕A),(10↑10⌽⎕A),'!?,.',6↑⌽⎕A

This works on Dyalog APL. I managed to save a couple characters by generating the output string (everything after ). I'll write up an explanation when I get some time!

Here's how the output looks:

      ⍪3,/(1⌽⎕D),(⌽10↑⎕A),(10↑10⌽⎕A),'!?,.',6↑⌽⎕A
 123 
 234 
 345 
 456 
 567 
 678 
 789 
 890 
 90J 
 0JI 
 JIH 
 IHG 
 HGF 
 GFE 
 FED 
 EDC 
 DCB 
 CBA 
 BAK 
 AKL 
 KLM 
 LMN 
 MNO 
 NOP 
 OPQ 
 PQR 
 QRS 
 RST 
 ST! 
 T!? 
 !?, 
 ?,. 
 ,.Z 
 .ZY 
 ZYX 
 YXW 
 XWV 
 WVU

Explanation, from right to left:

  • First, we construct the string seen in all of the other entries:
    • 6↑⌽⎕A: ⎕A gives us a string of the uppercase alphabet, from A to Z. We then reverse it () and take () the first 6 characters of it, giving us 'ZYXWVU'. (In retrospect, this approach doesn't end up saving any characters, but I'll leave it because it fits in better.)
    • '!?,.',: We concatenate (,) the string '!?,.' with the previous result.
    • (10↑10⌽⎕A),: We take the first 10 characters (10↑) of the alphabet, which is first rotated ten times (10⌽), and concatenate this with the previous result. As an example of rotation, 5⌽'abcdef' (the string 'abcdef' rotated 5 times) gives us 'cdefab'.
    • (⌽10↑⎕A),: Take the first 10 characters of the alphabet and reverse them, and concatenate this with the previous string.
    • (1⌽⎕D),: ⎕D gives us the digits as a string, from 0 to 9, inclusive. We then rotate ('⌽') this string by 1, yielding '1234567890'. As before, we concatenate this with the previous result.
  • Now that we have our string built (which saved us 3 characters from the APL representation, due to surrounding quotes), we do some magic to build our final output:
    • 3,/: We take the string, in groups of three characters, and concatenate them.
    • To finish it off, we use to ravel our vector of strings (really a vector of character vectors) along the first dimension. This has the effect of changing its shape from 38 to 38 1 (a 38x1 matrix).
\$\endgroup\$
4
\$\begingroup\$

R (75 characters)

embed(strsplit("1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU","")[[1]],3)[,3:1]

What does this do?

  • strsplit splits a string into substrings, in this case individual characters
  • embed is a really useful function that turns a vector into an array of overlapping elements
  • The rest is just indexing and sorting columns in the right order.

This produces and prints an array of characters:

> embed(strsplit("1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU","")[[1]],3)[,3:1]
      [,1] [,2] [,3]
 [1,] "1"  "2"  "3" 
 [2,] "2"  "3"  "4" 
 [3,] "3"  "4"  "5" 
 [4,] "4"  "5"  "6" 
 [5,] "5"  "6"  "7" 
 [6,] "6"  "7"  "8" 
 [7,] "7"  "8"  "9" 
 [8,] "8"  "9"  "0" 
 [9,] "9"  "0"  "J" 
[10,] "0"  "J"  "I" 
[11,] "J"  "I"  "H" 
[12,] "I"  "H"  "G" 
[13,] "H"  "G"  "F" 
[14,] "G"  "F"  "E" 
[15,] "F"  "E"  "D" 
[16,] "E"  "D"  "C" 
[17,] "D"  "C"  "B" 
[18,] "C"  "B"  "A" 
[19,] "B"  "A"  "K" 
[20,] "A"  "K"  "L" 
[21,] "K"  "L"  "M" 
[22,] "L"  "M"  "N" 
[23,] "M"  "N"  "O" 
[24,] "N"  "O"  "P" 
[25,] "O"  "P"  "Q" 
[26,] "P"  "Q"  "R" 
[27,] "Q"  "R"  "S" 
[28,] "R"  "S"  "T" 
[29,] "S"  "T"  "!" 
[30,] "T"  "!"  "?" 
[31,] "!"  "?"  "," 
[32,] "?"  ","  "." 
[33,] ","  "."  "Z" 
[34,] "."  "Z"  "Y" 
[35,] "Z"  "Y"  "X" 
[36,] "Y"  "X"  "W" 
[37,] "X"  "W"  "V" 
[38,] "W"  "V"  "U" 
\$\endgroup\$
1
  • \$\begingroup\$ +1 embed is very useful function indeed! \$\endgroup\$
    – Tommy
    Commented Dec 2, 2011 at 18:34
4
\$\begingroup\$

Scala 70 chars:

"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU".sliding(3,1).mkString("\n")
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 73

I independently arrived at the same method as everyone else:

Grid@Partition[Characters@"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU",3,1]
\$\endgroup\$
2
\$\begingroup\$

Groovy, 73

(0..37).each{println"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"[it..it+2]}

All the clever stuff I tried turned out to be longer than doing it the dumb way.

\$\endgroup\$
0
2
\$\begingroup\$

Python, 73

for i in range(38):print"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"[i:i+3]
\$\endgroup\$
2
\$\begingroup\$

C, 98 104 characters

Since no one else has done so yet, I thought I would try actually generating the string on the fly, using some kind of run-length encoding for ascending and descending runs.

EDIT: After a number of iterations, here's finally a "clever" solution that ties with the shortest "dumb" solution in C at 98 characters:

char*s="0º.ÿK»Jº ü=ÿ*ø[×",a[99],*p=a,i;main(j){for(;i-=i<8?j=*s++,*s++:8;puts(p++))p[2]=j+=i%4-1;}

The code requires an 8-bit Latin-1 encoding (ISO-8859-1 or Windows-1252), which should work fine on all commonly used platforms, but saving the source with some less popular 8-bit code page, or UTF-8 will not work.

The data string was created by the following piece of emacs lisp:

(require 'cl)
(apply 'concat
  (let ((last-remainder 0))
    (loop for (begin count step twiddle)
          in '((?1 9 +1 4) (?0 1 +2 4) (?J 10 -1 4) (?K 10 +1 0)
               (?! 1 +1 4) (?? 1 +2 4) (?, 2 +2 4) (?Z 6 -1 8))
          append (prog1 (list (char-to-string (- begin step))
                              (char-to-string 
                               (logand 255 (- last-remainder
                                              (+ (* 8 (- count 1)) (+ step 1)
                                                 twiddle)))))
                   (setq last-remainder (+ (logand twiddle 7) step 1))))))

The "twiddle" bit is used to avoid unprintable ASCII control characters in the encoded data string, and to ensure that i==0 only at the end of the output.

C, 98 characters

However, even in C you can get a short program by simply printing consecutive triplets from the original string:

main(){char s[]="12,34567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU",*p=s+2;for(;*p=p[1];puts(p-3))*++p=0;}
\$\endgroup\$
2
\$\begingroup\$

Ruby 69 65 62

Based on Groovy example

38.times{|i|p"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"[i,2]}
\$\endgroup\$
1
  • \$\begingroup\$ I think the convention here in the past for multiple answers in different languages has been to post one answer for each language. \$\endgroup\$
    – Gareth
    Commented Jan 15, 2012 at 18:34
2
\$\begingroup\$

Haskell, 80

mapM_(putStrLn.take 3.(`drop`"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"))[0..37]
\$\endgroup\$
2
\$\begingroup\$

Kotlin, 140 71 bytes

"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU".windowed(3).map{println(it)}

Try it online!

I just realized it's easier to use the string itself instead of generating it using ranges.

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

Javascript, 103

for(a='1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU';a.length>2;a=a.substring(1))console.log(a.substr(0,3))
\$\endgroup\$
1
  • 3
    \$\begingroup\$ An anonymous user suggested reducing this to 93 chars as for(a='1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU';a[3];a=a.slice(1))console.log(a.slice(0,3)) \$\endgroup\$ Commented Dec 22, 2011 at 7:33
1
\$\begingroup\$

Haskell, 94

main=putStr.unlines.take 38$take 3`map`iterate tail"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"
\$\endgroup\$
1
\$\begingroup\$

Perl, 73 characters:

print substr('1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU',$_,3),$/for 0..37

Perl, 66 characters:

say substr"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU",$_,3for 0..37

when called by:

perl -E 'say substr"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU",$_,3for 0..37'
\$\endgroup\$
1
\$\begingroup\$

D 124 chars

import std.stdio;void main(){enum s="1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU";
foreach(i;3..s.length){writeln(s[i-3..i)]);}}
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 83 chars

for(i=0;i<38;)console.log('1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'.substr(i++,3))

Decided to see if I could beat stephencarmody's solution. This is what I came up with.

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

Smalltalk 102 99

1to:38 do:[:i|x:='1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'copyFrom:i to:i+2.Transcript cr show:x]

I don't know Smalltalk very well so it's a little bit strange to me. It's compiles with gst others are not tested.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ First trick: remove the space between 38 and do: -> 98 - second trick to remove another space, loop from 3to:40 and copyFrom:i-2to:i ->97 - third trick, don't use a variable x:=... show:x, just show:('...'copyFrom:i-2to:i) directly, that's -4 chars + 2 parenthesis ->95 \$\endgroup\$
    – aka.nice
    Commented May 4, 2013 at 13:54
1
\$\begingroup\$

Q (66 63 chars)

(((!)38),'3)sublist\:"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"
\$\endgroup\$
1
\$\begingroup\$

Prolog, 131

This is probably why you never see Prolog entries. The newline is required (actually, any whitespace will do but there has to be whitespace).

z(S,L):-append(_,X,L),append(S,_,X),length(S,3).
:-forall(z(X,"1234567890JIHFEDCBAKLMNOPQRST!?,.ZYXWVU"),writef("%s\n",[X])),halt.
\$\endgroup\$
1
\$\begingroup\$

///, 151 bytes

123
234
345
456
567
678
789
890
90J
0JI
JIH
IHG
HGF
GFE
FED
EDC
DCB
CBA
BAK
AKL
KLM
LMN
MNO
NOP
OPQ
PQR
QRS
RST
ST!
T!?
!?,
?,.
,.Z
.ZY
ZYX
YXW
XWV
WVU

Try it online!

Can't golf it more? This is, in a sense, <152 bytes.

\$\endgroup\$
4
  • \$\begingroup\$ This is not a serious contender by our rules. You make no effort to do better than the minimum score. \$\endgroup\$
    – user45941
    Commented Oct 4, 2016 at 15:48
  • \$\begingroup\$ I can't, that's why I posted it as-is. If you think you could do better, you can try. I don't know of any shorter solution, and, in fact, I did put some effort in, but realized that this isn't ever going to be further golfed down. \$\endgroup\$ Commented Oct 4, 2016 at 16:24
  • \$\begingroup\$ I'm not convinced that this can be golfed at all in ///, but the spec says the program must be shorter than [...] the string it outputs, which isn't the case here. \$\endgroup\$
    – Dennis
    Commented Oct 4, 2016 at 17:21
  • \$\begingroup\$ @Dennis No, it says the program must be smaller than 152 bytes (151 < 152). I think it's an error, or I read the post differently, but i.e. does not override the meaning of something, it just helps you to better understand it, in my sense. Also, I didn't include a trailing newline, maybe that's why this is 151 bytes. And yes, I read that section. \$\endgroup\$ Commented Oct 5, 2016 at 14:18
1
\$\begingroup\$

Jelly, 41 40 bytes

ØAḣ⁵Ṛ
ØDṫ2;0;¢;“KLMNOPQRST!?,.ZYXWVU”ṡ3Y

Try it online!

Might (still) be golfable...

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

Jelly, 24 23 bytes

ØDṙ1;ØA;“.,?!”s⁵UÐeFṡ3Y

Try it online!

Generates the keyboard top to bottom left to right, then boustrophedonizes it afterwards.

ØD                         "0123456789"
  ṙ1                       rotated once to the left
    ;                      concatenated with
     ØA                    the uppercase alphabet
       ;“.,?!”             concatenated with ".,?!".
              s            Chop it into slices of length
               ⁵           10,
                U          (vectorized) reverse
                 Ðe        the slices at even 1-indices,
                   F       smash the slices back together,
                    ṡ3     take every contiguous sublist of length 3,
                      Y    and join on newlines.
\$\endgroup\$
1
\$\begingroup\$

Brachylog, 26 bytes

Ị↺,Ạ,".,?!"ụḍ₄{i↔ⁱ⁾}ᶠcs₃ẉ⊥

Try it online!

Essentially a translation of my Jelly answer. A full program which prints the desired output with a trailing newline.

Ị                             "0123456789"
 ↺                            rotated once to the left
  ,                           concatenated with
   Ạ                          the alphabet (lowercase)
    ,".,?!"                   concatenated with ".,?!",
           ụ                  uppercased,
            ḍ₄                sliced into quarters.
                     c        Concatenate
              {    }ᶠ         every possible result from
               i              taking a slice with its 0-index
                ↔             and reversing it
                 ⁱ⁾           a number of times equal to the index.
                        ẉ     Print with a newline
                      s₃      a substring of length 3 from the concatenation,
                         ⊥    then try again with a different substring.

If a trailing newline is unacceptable:

Brachylog, 27 bytes

Ị↺,Ạ,".,?!"ụḍ₄{i↔ⁱ⁾}ᶠcs₃ᶠ~ṇ

Try it online!

Outputs as a function.

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

05AB1E, 24 bytes

žhÀAu".,?!"«Tô2Å€R}J«ü3»

Try it online.

Minor alternative:

Au".,?!"«TôžhÀšεNFR]Jü3»

Try it online.

Explanation:

žh                       # Push builtin "0123456789"
  À                      # Rotate it once to the left: "1234567890"
   Au                    # Push the uppercase alphabet
     ".,?!"«             # Append ".,?!" to it
            Tô           # Split it into parts of size 10:
                         #  ["ABCDEFGHIJ","KLMNOPQRST","UVWXYZ.,?!"]
              2Å€ }      # For every 2nd item (0-based index modulo 2 == 0):
                 R       #  Reverse it
                         #   ["JIHGFEDCBA","KLMNOPQRST","!?,.ZYXWVU"]
                   J     # Join the list together to a single string again:
                         #  "JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"
                    «    # Merge it to the digits:
                         #  "1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"
                     ü3  # Create overlapping triplets
                       » # Join the list by newlines
                         # (after which it is output implicitly with trailing newline)

Au".,?!"«Tô              # Same as above: ["ABCDEFGHIJ","KLMNOPQRST","UVWXYZ.,?!"]
           žhÀ           # Same as above: "1234567890"
              š          # Prepend it to the list:
                         #  ["1234567890","ABCDEFGHIJ","KLMNOPQRST","UVWXYZ.,?!"]
               ε         # Map each string to:
                NF       #  Loop the 0-based map-index amount of times:
                  R      #   Reverse the string every iteration
                   ]     # Close both the loop and map
                    J    # Join the list together to a single string again:
                         #  "1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"
                     ü3» # Same as above
                         # (after which it is output implicitly with trailing newline)
\$\endgroup\$
0
\$\begingroup\$

Q, 63

{(x;3)sublist"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"}'[(!)38]
\$\endgroup\$
0
\$\begingroup\$

x86-16 machine code, PC DOS, 64 bytes

Binary:

00000000: b409 bb1b 01ba 1801 bf0a 24b1 2687 3fcd  ..........$.&.?.
00000010: 2187 3f42 43e2 f6c3 3132 3334 3536 3738  !.?BC...12345678
00000020: 3930 4a49 4847 4645 4443 4241 4b4c 4d4e  90JIHGFEDCBAKLMN
00000030: 4f50 5152 5354 213f 2c2e 5a59 5857 5655  OPQRST!?,.ZYXWVU

Listing:

BB 011B     MOV  BX, OFFSET KB+3        ; pointer to end of 3 char substring 
BA 0118     MOV  DX, OFFSET KB          ; pointer to beginning of 3 char substring 
BF 240A     MOV  DI, 240AH              ; string '$' + 0AH 
B1 26       MOV  CL, 38                 ; number of lines 
B4 09       MOV  AH, 9                  ; DOS API output string function     
        CLOOP: 
87 3F       XCHG DI, WORD PTR[BX]       ; swap string term and LF char after 3 chars 
CD 21       INT  21H                    ; write substring to console 
87 3F       XCHG DI, WORD PTR[BX]       ; swap back 
42          INC  DX                     ; increment string start pointer 
43          INC  BX                     ; increment string end pointer 
E2 F6       LOOP CLOOP                  ; loop until 38 lines 
C3          RET                         ; return to DOS
        KB: 
            DB  '1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'

It's a bit of a naïve approach, but still fits well below the spec size (and is a nice power of 2). Loops through the string and swaps the relative 4th and 5th character with a LF followed by a string terminator and then outputs it.

Standalone DOS executable COM program. Output:

Head:

enter image description here

Tail:

enter image description here

\$\endgroup\$
0
\$\begingroup\$

Japt -R, 27 bytes

;9õ pUB".,?!" ¬ò10 ËzEÑìã3

Test it

;9õ pUB".,?!" ¬ò10 ËzEÑìã3
 9õ                             :Range [1,9]
    p                           :Push
     U                          :  0
;     B                         :  Uppercase alphabet
       ".,?!"                   :  String literal
              ¬                 :Join
               ò10              :Partitions of length 10
                   Ë            :Map each string a 0-based index E
                    z           :  Rotate clockwise 90 degrees
                     EÑ         :  E*2 times
                       Ã        :End map
                        ¬       :Join
                         ã3     :Substrings of length 3
                                :Implicit output, joined with newlines
\$\endgroup\$
0
\$\begingroup\$

PowerShell 6+, 62 bytes

0..37|%{'1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU'|% s*g $_ 3}

Try it online!

where s*g is the shorcut for the Substring method.

\$\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.