Circular Keyboard Spiral

24

3

This is a QWERTY keyboard.

Q W E R T Y U I O P
 A S D F G H J K L
  Z X C V B N M

We can "spiral out" on this keyboard, starting from G. The spiral will start at G, go to H, then to Y, then to T, then F, then V, then B, then N, then J, then U, then R, then D, then C,... etc. Your challenge is to, given a number 1 ≤ N ≤ 26, output the first N characters in this spiral. (If you are confused, refer to the pictures at the end of the post.)

The catch? Your program's score is proportional to the indices of characters found inside the spiral!

Scoring

  1. For every letter (case-insensitive) in your code, add the index of that character in the spiral to your score (starting from 1).
  2. For every character not in the spiral, add 10 to your score.
  3. The lowest score wins.

For example, the program print("Hello, World!") has a score of 300.

For your convenience, I have written an automatic program grader.

var SPIRAL = "GHYTFVBNJURDCMKIESXLOWAZPQ";
function grade(program) {
    var score = 0;
    for(var i = 0; i < program.length; i++) {
        if(/^[A-Za-z]$/.test(program[i])) {
            score += SPIRAL.indexOf(program[i].toUpperCase()) + 1;
        }
        else {
            score += 10;
        }
    }
    return score;
}

input.oninput = function() {
    output.value = "Your program's score is: " + grade(input.value);
}
textarea { width: 500px; height: 6em; font-style: monospace; }
<textarea id="input"></textarea>
<textarea disabled id="output"></textarea>

Other rules

  • Your submission may be a program or function.
  • You may take N starting at 0 or 1 and ending at 25 or 26, respectively, but the outputs should still begin with "G" and end with "GHYTFVBNJURDCMKIESXLOWAZPQ".
  • You must output the characters in the spiral in order.
  • If a function, you may return a list of characters instead of a string.
  • You may have one trailing newline following the output.
  • You may use lowercase letters instead of uppercase letters, or a combination of both.

Test cases

number -> output
1 -> G
2 -> GH
5 -> GHYTF
12 -> GHYTFVBNJURD
15 -> GHYTFVBNJURDCMK
24 -> GHYTFVBNJURDCMKIESXLOWAZ
26 -> GHYTFVBNJURDCMKIESXLOWAZPQ

Pictures

regular keyboard

The spiral superimposed:

spiral keyboard

Conor O'Brien

Posted 2017-11-29T02:06:28.003

Reputation: 36 228

3Someone has watched Sphere recently... – Pureferret – 2017-11-29T14:47:10.387

@Pureferret Could you enlighten me? I'm not sure what you refer to. – Conor O'Brien – 2017-11-29T14:48:06.867

@ConorO'Brien In Sphere (both the novel and movie), an alien communicates with humans using a two-digit numeric code where each number corresponds to a letter on the keyboard in a very similar pattern.

– Engineer Toast – 2017-11-29T15:02:39.317

Answers

14

Japt, 304 264 162 points

Saved 40 points thanks to @ConorO'Brien

;î"历锋㫿鮹㿬崴ꨜꎋΞ"csG

Test it online!

In order to save as many points as possible, the entire string is condensed into 9 Unicode chars by interpreting each run of 3 letters as a base-36 number, then converting to a code point. The program itself takes this compressed string (which costs 110 points, including the quotes) and maps each charcode by converting it to a string in base-36 (G after the ; at the beginning). î takes the first {input} chars of this, which is implicitly printed.

ETHproductions

Posted 2017-11-29T02:06:28.003

Reputation: 47 880

11

C, score: 544

g(g){write(1,"GHYTFVBNJURDCMKIESXLOWAZPQ",g);}

Try it online!

Steadybox

Posted 2017-11-29T02:06:28.003

Reputation: 15 798

...why are you naming the function the same thing as the argument? – Fund Monica's Lawsuit – 2017-11-29T09:12:50.850

6@QPaysTaxes Because g is the cheapest letter per the scoring used in the challenge. – Steadybox – 2017-11-29T09:13:36.657

Ah, I missed the custom scoring. – Fund Monica's Lawsuit – 2017-11-29T09:16:21.337

11

Spiral, score:  61921   5127   4715   4655  4191

4.X~>v+^#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v
   X *   X X X X X X X X X X X X X X X X X X X X X X X X X
   ! >   h y t f V b n j u [ ( 1 3 2 ) ] U J N B F T Y H G
0;vgv*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*vvv****v+^v+^v+^v+^*v++4
    X X X X X X X X X X X X X X X X X X X X X X X X X X
    v v v v v v v v v v v v v v v v v v v v v v v v v v
    Y y J F V u t U [ G H B n 3 N 2 j ) h g f ] ( 1 b T

An interpreter can be found here.

Explanation:

P.X~ZZ*v+^#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v
   X       X X X X X X X X X X X X X X X X X X X X X X X X X
   !       h y t f V b n j u r d c m k i e s x l o w a z p q
0;vgv*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*****************************************************************vP
    X X X X X X X X X X X X X X X X X X X X X X X X X X
    v v v v v v v v v v v v v v v v v v v v v v v v v v
    z y x w V u t s r q p o n m l k j i h g f e d c b a

The program begins at the 0 character on the fourth line. The first piece of code to run is 0;vg. ; takes a number as input and places it in the stack. v places what is in the register (a zero) into the stack. It will be used as the counter. g is a label, when it is reached, the control jumps to the other occurence of the letter g in the code.

So this is where the control is now:

X
v
g

Since there is whitespace in all other directions, the instruction pointer starts moving upwards. v places a zero into the stack, and X pops it from the stack immediately. Because the popped value is zero, the instruction pointer moves to X (otherwise it would treat it as whitespace).

By default, the control flow is in turn-right mode, so now when it reaches the junction, the instruction pointer turns to the right. v yet again pushes a zero into the stack, * increments the register by one.

v*v*v
  X
  v
  g

The next v places what is in the register (number 1) into the stack, the instruction pointer attempts to turn to the right, hitting the next X. The value just added to the stack is popped and placed in the register. Because it is non-zero, X is not entered, and the IP proceeds to the next * on the right instead, again incrementing the value in the register.

v*v*v*v*v
X X X X X
v v v v v
i h g f e

This happens again and again until we reach the end of this part and the line of *s begins. By now the value in the register is 6, which is ASCII letter g minus ASCII letter a. Thus with a line of 97 *s we increment the value in the register to 103, which matches the letter g we want to print. v pushes it into the stack, and P is another label upon hitting which we jump to the other P on the first line of the code.

Here . pops the value from the stack and prints it as a character. After that X pops the extraneous zero from the stack, then ~ compares the two remaining values in the stack (the values being the counter and the input value). If the values are the same, the operator places zero in the stack (otherwise -1 or 1). Again, the control attempts to turn right. X pops the value of the comparison from the stack, if it is zero, X, and after it ! is entered, terminating the program.

P.X~ZZ*v+^
   X
   !

Otherwise the IP continues to the Z, which is a label which in this case jumps only one step to the right. The reason for doing this is that jumping sets the value in the register back to zero. * increments the register and v places the resulting 1 into the stack. + pops the two top elements of the stack (the 1 and the counter), adds them, and places the result in the stack (in effect this increments the counter by one). ^ copies the result from the stack to the register without removing it from the stack.

# decrements the value in the register by one, v pushes the decremented value to the stack, the IP attempts to turn to the right, and the X pops the value from the stack. If the value is non-zero the IP keeps moving to the east, decrementing the value in the register, until it hits zero, and the IP enters an X branch.

#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v
 X X X X X X X X X X X X X X X X X X X X X X X X X
 h y t f V b n j u r d c m k i e s x l o w a z p q

The branch leads to a label corresponding to the value of the counter. Upon hitting the label, the control jumps to the other occurence of the label in the section where we started with the label g, starting another iteration. As with the g, the value in the register gets incremented up to the ASCII value of the letter we need to print. Then the character is printed and the counter incremented, another label is selected. This happens until after the last iteration the counter equals the input, and the program terminates.

Edit:

P.X~Zv+^
   X *
   ! Z

Achieves the same thing as

P.X~ZZ*v+^
   X
   !

but with less whitespace.

Edit 2:

vv****v+^v+^v+^v+^*v++P

Can be used instead of:

*****************************************************************vP

Steadybox

Posted 2017-11-29T02:06:28.003

Reputation: 15 798

2Ironic that a languaje called "Spiral" has such a high score in a spiral output problem. – Shirkam – 2017-11-29T10:10:52.093

6

Haskell, 471

(`take`"GHYTFVBNJURDCMKIESXLOWAZPQ")

Try it online!

This is a bit of a benchmark, I feel like there must be a better way, but its the best I've found so far.

Explanation

I suppose I should explain this for those not familiar with Haskell too well. The function take takes the first n elements of the list. It is called like this:

take n list

We want to take the first n elements of the sting "GHYTFVBNJURDCMKIESXLOWAZPQ", so we want something like

f n=take n"GHYTFVBNJURDCMKIESXLOWAZPQ"

We can do better though, we can infix take using backticks

f n=n`take`"GHYTFVBNJURDCMKIESXLOWAZPQ"

And now this can be made pointfree

(`take`"GHYTFVBNJURDCMKIESXLOWAZPQ")

Post Rock Garf Hunter

Posted 2017-11-29T02:06:28.003

Reputation: 55 382

It's a shame partial application requires using partial in Clojure. This is what I was going for, but partial was too expensive. – Carcigenicate – 2017-11-29T02:37:00.790

3Isn't your score 470? That's what the snippet in the question is giving me anyway... – Just a student – 2017-11-29T08:33:45.823

5

Jelly, 211 score

19 bytes

“eȷÞ('¢ạẓkȮV’œ?ØAðḣ

Try it online!

saved a bunch of score thanks to Emigna's suggestion to use œ? :D

HyperNeutrino

Posted 2017-11-29T02:06:28.003

Reputation: 26 575

5

Vim, 461 418

CGHYTFVBNJURDCMKIESXLOWAZPQg^[G@" D

Thanks @pacholik for -43 score!

Try it online!

vim-animation

ბიმო

Posted 2017-11-29T02:06:28.003

Reputation: 15 345

1Make it 418 with CGHYTFVBNJURDCMKIESXLOWAZPQg©G@" D (© is escape) – pacholik – 2017-11-29T09:04:03.337

4

TI-Basic (TI-84 Plus CE), 454 432 points

sub("GHYTFVBNJURDCMKIESXLOWAZPQ",1,Ans

-22 points from Conor O'Brien

Run with 5:prgmNAME.

Returns/prints the substring from 1 to Ans (the number input).

TI-Basic is a tokenized langauge, so I'm scoring this by the byte values of the tokens.

sub( is 0xbb 0x0c, so 20

" is 0x2a, so *, so 10*2=20

Uppercase letters don't change, so the string is 351

, is 0x2b, so +, so 10*2=20

1 is 0x31, so 1, so 10

Ans is 0x72, which is r, so 11

20 + 20 + 351 + 20 + 10 + 11 = 432

pizzapants184

Posted 2017-11-29T02:06:28.003

Reputation: 3 174

With this interpretation of the scoring rules, you can save 31 more bytes by looking for the letters in creative places. Replace the S, A, Z, P by the stat variables s, a, z, p (in the STAT + 5 menu), which score 17 points each: they're 2-byte tokens whose first byte corresponds to b. Replace the O, W, Q by the ordinary lowercase letters, which score 20 points each: they're 2-byte tokens 0xBBBF, 0xBBC7, 0xBBC1. – Misha Lavrov – 2017-11-29T08:03:50.647

4

Befunge, Score: 531

QPZAWOLXSEIKMCDRUJNBVFTYHG"&\>,# 1#\-# :# _@

I feel this challenge would have been more interesting if the output had to be in a spiral as well.

Jo King

Posted 2017-11-29T02:06:28.003

Reputation: 38 234

3

Python 3, score = 762 753

1-based input. This is worse than the trivial approach, since it uses 37 non-letters. It is somewhat interesting, though.

-9 thanks to Leo.

h=lambda g:g and h(g-1)+chr(65+int('GYGGYHGYYGYTGTYHGYGGHGGTGHGYGYGFGHGGYGGHHGGHHYYGHGHGGYFGGYHGGTHGHTGGGGGFGGVHGT'[g*3-3:g*3],35)%26)or''

Try it online!

Colera Su

Posted 2017-11-29T02:06:28.003

Reputation: 2 291

1I like this approach :) By the way [:g*3][-3:] can become [g*3-3:g*3] lowering the total score by 9 points – Leo – 2017-11-29T03:51:18.170

3

05AB1E, score: 204

.•3ŽγY
₁ùÐÁo0ª ’ö:•£

Try it online!

Emigna

Posted 2017-11-29T02:06:28.003

Reputation: 50 798

1I wondered why it was cached hah! – Magic Octopus Urn – 2017-11-30T01:17:36.083

2

Brainf**k, score = 2690

Input a single byte ranging from 0x1 to 0x1a.

>>++++>+++>>>>++++++++++[<+<-<+>>>-]<<--<+++>>>++>->+++++++++++>++++++>-------->---->-->>---------->--------->+++++>++++++++>--->+>----------->+++++++++>------->+++++++>++++++++++++>----->------>+>>+++++++[<+++++++++++[<[[+<]+<]>->[[>]>]<<<-]>-]<<[-]>,[[<]<.[-]>+[>]<-]

Try it online!

Colera Su

Posted 2017-11-29T02:06:28.003

Reputation: 2 291

2

APL (Dyalog), score: 391

↑∘'GHYTFVBNJURDCMKIESXLOWAZPQ'

Try it online!

The only use for Latin letters in Dyalog is in variable names and some system functions. Apart from that, only glyphs and some Greek letters are used.

Uriel

Posted 2017-11-29T02:06:28.003

Reputation: 11 708

1

Python 3, 522

lambda g:"GHYTFVBNJURDCMKIESXLOWAZPQ"[:g]

Try it online!

An anonymous lambda utilizing Python's slicing of strings ("asdf"[:i] gets the first i characters of "asdf")

pizzapants184

Posted 2017-11-29T02:06:28.003

Reputation: 3 174

1

Clojure, 484 474 points

-10 points because apparently a % can exist after a number without a space separating them!? I might have to go back over and improve some submissions.

#(subs"ghytfvbnjurdcmkiesxlowazpq"0%)

An anonymous function. Basically a Clojure port of what's already been posted. Scores nicely! I think this is the first Clojure program I've ever written that doesn't contain a single space.

(defn spiral [n]
  ; Substring the hardcoded list, going from index 0 to n
  (subs "ghytfvbnjurdcmkiesxlowazpq" 0 n))

Carcigenicate

Posted 2017-11-29T02:06:28.003

Reputation: 3 295

1

Ly, 521 points

"QPZAWOLXSEIKMCDRUJNBVFTYHG"ns[,spol];

Try it online!

I don't feel as though this is optimizable.

LyricLy

Posted 2017-11-29T02:06:28.003

Reputation: 3 313

1

Bash, score: 465

cut -b-$1<<<GHYTFVBNJURDCMKIESXLOWAZPQ

Try it online!

ბიმო

Posted 2017-11-29T02:06:28.003

Reputation: 15 345

1

Husk, 293 bytes

↑¨ghytfvb⌋ȷÜdcmkÏexl⁰Λzpq

This is the shortest one I could find, next closer ¨gHYtfvB⌋ȷÜdCmkÏex←ẆAzpq¨ for a score of 293..

Try it online!

Explanation

Brute-force search, turns out all lower-case gave the best score. It's basically the same as @Wheat Wizard's solution, take () on a compressed string (¨).

ბიმო

Posted 2017-11-29T02:06:28.003

Reputation: 15 345

1

Common Lisp, score: 580

(subseq"GHYTFVBNJURDCMKIESXLOWAZPQ"0(read))

Try it online!

Renzo

Posted 2017-11-29T02:06:28.003

Reputation: 2 260

1

Excel, 490 points

=LEFT("GHYTFVBNJURDCMKIESXLOWAZPQ",A1)

Convention for Excel ansers is to take input from A1. Changing this to G1 cuts 22 points (468).

=LEFT("GHYTFVBNJURDCMKIESXLOWAZPQ",G1)

Wernisch

Posted 2017-11-29T02:06:28.003

Reputation: 2 534

1

C#, score 546

g=>"GHYTFVBNJURDCMKIESXLOWAZPQ".Substring(0,g);

auhmaan

Posted 2017-11-29T02:06:28.003

Reputation: 906

1

Rust, score 443

It is not often that Rust is good at code golf but here it beats many languages

|g|&"GHYTFVBNJURDCMKIESXLOWAZPQ"[..g]

raggy

Posted 2017-11-29T02:06:28.003

Reputation: 491

1

Golang, score 861

func g(g int){io.WriteString(os.Stdout,"GHYTFVBNJURDCMKIESXLOWAZPQ"[0:g])}

Play it online !

Addict

Posted 2017-11-29T02:06:28.003

Reputation: 31

1

Javascript ES6, 527 points

g=>`GHYTFVBNJURDCMKIESXLOWAZPQ`.slice(0,g)

Try it !

f=g=>`GHYTFVBNJURDCMKIESXLOWAZPQ`.slice(0,g)

input.oninput = function() {
    output.value = f(input.value);
}
textarea { width: 500px; height: 6em; font-style: monospace; }
<textarea id="input"></textarea>
<textarea disabled id="output"></textarea>

Weedoze

Posted 2017-11-29T02:06:28.003

Reputation: 931

1

PHP, 590 points

<?=substr(GHYTFVBNJURDCMKIESXLOWAZPQ,0,$argv[1]);

Try it online!

roberto06

Posted 2017-11-29T02:06:28.003

Reputation: 351

1

PHP, score 584

fiddled a bit with the dictionary; the fact that xoring the string cuts it off rendered substr obsolete.

<?=">1 -?/;73,+=:420<*!56.8#)("^str_repeat(y,$argv[1]);

Try it online.

Titus

Posted 2017-11-29T02:06:28.003

Reputation: 13 814

0

Perl, score 568 517

Thanks to Nahuel Fouilleul for saving 51 points.

($_)=GHYTFVBNJURDCMKIESXLOWAZPQ=~/.{$_}/g

Try it online!

Zaid

Posted 2017-11-29T02:06:28.003

Reputation: 1 015

GHYTFVBNJURDCMKIESXLOWAZPQ=~/.{$_}/;$_=$& + -p = 501+25 – Nahuel Fouilleul – 2017-11-30T14:27:34.870

Yes that'll work. Do you know how to set up the inputs on TIO? I struggled a lot yesterday – Zaid – 2017-11-30T14:36:42.597

yes below > input for standrad input instead of > arguments (for command line parameters) – Nahuel Fouilleul – 2017-11-30T15:09:06.790

($_)=GHYTFVBNJURDCMKIESXLOWAZPQ=~/.{$_}/g better = 492 +25 – Nahuel Fouilleul – 2017-11-30T15:18:14.263

0

Mathematica, 528

"GHYTFVBNJURDCMKIESXLOWAZPQ"~StringTake~#&

Try it online!

J42161217

Posted 2017-11-29T02:06:28.003

Reputation: 15 931

0

Pyth, score: 371

<"GHYTFVBNJURDCMKIESXLOWAZPQ

Try it here.

How?

<"GHYTFVBNJURDCMKIESXLOWAZPQ"Q   implicit string end, implicit input
<                            Q   first Q(=input) elements ...
 "GHYTFVBNJURDCMKIESXLOWAZPQ"    ... of this string

ovs

Posted 2017-11-29T02:06:28.003

Reputation: 21 408

0

Ruby, 453 points

->g{'GHYTFVBNJURDCMKIESXLOWAZPQ'[0,g]}

Try it online!

G B

Posted 2017-11-29T02:06:28.003

Reputation: 11 099

0

><>, 558+16= 574 points

<;v? : <{"GHYTFVBNJURDCMKIESXLOWAZPQ"
  >$o1-^

Uses the -v flag to push input onto the stack.

Pushes the spiral onto the stack in reverse order, then rotates the input to the top. Then, while the top of the stack is non-zero, prints the next letter and decrements the top of the stack.

Try it online!

KSmarts

Posted 2017-11-29T02:06:28.003

Reputation: 1 830

0

Pyth, 261 points

<."AZJ{Û§zoÆæÏýú

Try it here!

This outputs uppercase letter. For lowercase, you can try the alternative 261 byter.

Mr. Xcoder

Posted 2017-11-29T02:06:28.003

Reputation: 39 774

0

Julia 0.6, score 433

g->"GHYTFVBNJURDCMKIESXLOWAZPQ"[1:g]

Try it online!

gggg

Posted 2017-11-29T02:06:28.003

Reputation: 1 715