56
\$\begingroup\$

Inspired by a meme I saw earlier today.

Challenge description

Consider an infinite alphabet grid:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
...

Take a word (CODEGOLF in this example) and make it a subsequence of the grid, replacing unused letters by a space and removing letters at the end of the infinite grid altogether:

  C           O           
   DE G       O           
           L              
     F

Examples

STACKEXCHANGE

                  ST      
A C       K               
    E                  X  
  C    H                  
A            N            
      G                   
    E

ZYXWVUTSRQPONMLKJIHGFEDCBA

                         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

F

     F

ANTIDISESTABLISHMENTARIANISM

A            N     T      
        I                 
   D    I         S       
    E             ST      
AB         L              
        I         S       
       H    M             
    E        N     T      
A                R        
        I                 
A            N            
        I         S       
            M

Notes

  • Trailing whitespaces are allowed.
  • You don't need to pad the last any line with spaces. For example, if the input is ABC, you may output just ABC without 23 trailing spaces.
  • You may assume input will match [A-Z]+ regex.
  • Alternatively, you may use lower-case alphabet, in which case output will match [a-z]+.
  • You must use a newline (\n, \r\n or equivalent) to separate lines, that is a list of strings is not a proper output format.
  • This is a challenge, so make your code as short as possible!
\$\endgroup\$
  • \$\begingroup\$ Are leading newlines allowed? \$\endgroup\$ – Erik the Outgolfer Sep 2 '17 at 13:46
  • \$\begingroup\$ @EriktheOutgolfer Sure, as long as it doesn't mess up grid structure. \$\endgroup\$ – shooqie Sep 2 '17 at 13:49
  • \$\begingroup\$ Would it be okay if a non-fatal error stops the program? \$\endgroup\$ – Zacharý Sep 2 '17 at 21:07
  • \$\begingroup\$ @Zacharý Although I can see how that could save some bytes, I think it's ugly and produces undesired, superfluous output. So no. EDIT: Unless you can make your program non-fatally exit through an exit code or something that wouldn't print exception stack trace or something similar to stderr. \$\endgroup\$ – shooqie Sep 2 '17 at 21:09
  • 7
    \$\begingroup\$ Suggested test case: BALLOON (two adjacent characters that are the same). \$\endgroup\$ – Kevin Cruijssen Sep 4 '17 at 12:37

46 Answers 46

1
2
1
\$\begingroup\$

R, 95 bytes

Just run through the upper case alphabet repeatedly while advancing a counter by 1 if you encounter the letter in the counter position of the word and printing out the letter, a space otherwise.

function(s)while(F>""){for(l in LETTERS)cat("if"((F=substr(s,T,T))==l,{T=T+1;l}," "));cat("
")}

Try it online!

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

GolfScript, 37 bytes

64:a;{.a>{}{'
'\64:a;}if.a-(' '*\:a}%

Try it online!

I did a Golfscript one under a different name, but it had incorrect output.

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

Ruby -n, 62 bytes

Scans the input string for sequences of increasing letters, and for each sequence, replace letters not in the sequence with spaces.

g=*?A..?Z
$_.scan(/#{g*??}?/){puts g.join.tr"^#$&"," "if$&[0]}

Try it online!

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

05AB1E, 21 19 17 bytes

Çü@0šÅ¡vð₂×yAykǝ,

Try it online!

Ç       push a list of ascii values of the input        [84, 69, 83, 84]
ü@      determine which letter is >= the next letter    [1, 0, 0]
0š      prepend a 0 (false) to that list                [0, 1, 0, 0]
Å¡      split input on true values                      [["T"], ["E", "S", "T"]]
v       for each list entry
  ð₂×     push 26 spaces
  y       push list entry (letters)
  Ayk     push the positions of that letters in the alphabet
  ǝ       replace characters c in string a with letters b
  ,       print the resulting string
        implicitly close for-loop
\$\endgroup\$
0
\$\begingroup\$

Dyalog APL, 47 37 34 bytes

{↑{⍵∘{⍵∊⍺:⍵⋄' '}¨⎕A}¨⍵⊂⍨1,2≥/⎕A⍳⍵}

Try it online!

How? (argument is )

  • ⍵⊂⍨1,2≥/⎕A⍳⍵, split into alphabetically ordered segments
  • {...}¨, apply this function to each letter (argument is ):
    • ⎕A, the alphabet
    • ...¨, apply this function to each argument (argument is ):
      • ⍵∘, pass in as the left argument () to the function:
        • {⍵∊⍺:⍵⋄' '}, if is in , then return , otherwise a space. This function is what creates a line of text.
  • , turn into an array (equivalent of adding the newlines)
\$\endgroup\$
0
\$\begingroup\$

Mathematica, 73 71 72 bytes

Print@@(Alphabet[]/.Except[#|##,_String]->" ")&@@@Split[#,Order@##>0&];&
(* or *)
Print@@@Outer[If[!FreeQ@##,#2," "]&,Split[#,Order@##>0&],Alphabet[],1];&

sacrificed a byte to fix the output

Takes a list of lower case characters (which is a "string" per meta consensus).

Try it on Wolfram Sandbox

Usage

f = (Print@@(Alphabet[]/.Except[#|##,_String]->" ")&@@@Split[#,Order@##>0&];&)

 

f[{"c", "o", "d", "e", "g", "o", "l", "f"}]
 c           o           
  de g       o           
          l              
    f                    
\$\endgroup\$
  • 2
    \$\begingroup\$ Your input is a list of strings? Is this valid? \$\endgroup\$ – user73398 Sep 3 '17 at 0:00
  • 1
    \$\begingroup\$ Also this outputs {Null, Null, Null, Null} at the end. Is this allowed by OP? \$\endgroup\$ – user73398 Sep 3 '17 at 0:16
  • \$\begingroup\$ @BillSteihn Yes, per meta consensus. For your second question, it prints the string to STDOUT. The Nulls are what the expression evaluates to, not a part of STDOUT (you can see this easily on Mathematica Kernel). For now, I fixed the issue by adding a byte. \$\endgroup\$ – JungHwan Min Sep 3 '17 at 0:26
  • \$\begingroup\$ @BillSteihn the question specifies that a list of strings (i presume the list containing each line) is not a valid output format. I reckon it's fine as the input format, especially if it's a list of characters (plus, some languages have no distinction between a string and a list of characters, so disallowing this only makes the question unfair). \$\endgroup\$ – JungHwan Min Sep 3 '17 at 0:42
0
\$\begingroup\$

><>, 63 bytes

d5*v
(?;\i:0
~{?\}::{::}@=::{$" ["a${=:}?$~@?$~o10d2*-{?$~{+}}?

Try it online!

Input is expected in uppercase.

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

Kotlin, 133 131 129 bytes

fun r(s:String){var c=0
while(0<1){('A'..'Z').map{if(c==s.length)return
if(s[c]==it){print(s[c])
c++}else print(" ")}
println()}}

Try it online!

Explained

fun r(s: String) {
    // Current character
    var c = 0
    // Keep going until the end of the string
    while (0 < 1) {
        // Go through the letters
        ('A'..'Z').map{
            // If the word is done then stop
            // Have to check after each letter
            if (c == s.length) return
            // If we are at the right letter
            if (s[c] == it) {
                // Print it
                print(s[c])
                // Go to the next letter
                c++
            // Otherwise print space
            } else print(" ")
        }
        // Put a newline between the lines
        println()
    }
}

Test

fun main(args:Array<String>)=r("CODEGOLF")

Edit: Ran through my compressor, saved 2 bytes.

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

C++, 202 197 bytes

-5 bytes thanks to Zacharý

#include<iostream>
#include<string>
using c=std::string;void f(c s){std::cout<<c(s[0]-65,32)<<s[0];for(int i=1;i<s.size();++i)std::cout<<(s[i]>s[i-1]?c(s[i]-s[i-1]-1,32):"\n"+c(s[i]-65,32))<<s[i];}
\$\endgroup\$
  • \$\begingroup\$ I think (s[i]>s[i-1])=>s[i]>s[i-1] works, along with moving the int i=1 to the for-loop. \$\endgroup\$ – Zacharý Sep 9 '17 at 14:27
  • \$\begingroup\$ Also, ("\n"+c(s[i]-65,32)) => "\n"+c(s[i]-65,32) \$\endgroup\$ – Zacharý Sep 9 '17 at 14:32
0
\$\begingroup\$

PHP, 121 bytes

<?$p=$argv[1];$b=substr;while($p){for($i=A;$i!=AA;$i++){if($p[0]==$i){echo$b($p,0,1);$p=$b($p,1);}else echo" ";}echo'
';}

Try it online!

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

Kotlin, 101 bytes

Port of the Powershell.

{s:String->var p=' '
var x=""
var r=""
s.map{c->if(c<p){r+=x+"\n";x=""}
x=x.padEnd(c-'A')+c
p=c}
r+x}
\$\endgroup\$
0
\$\begingroup\$

Rust, 163 bytes

|s:&str|{let mut s=s.bytes().peekable();while s.peek().is_some(){for c in 65..91{print!("{}",if Some(c)==s.peek().cloned(){s.next();c}else{32}as char)}println!()}}

Try it online!

Explanation

|s:&str|{                                        // Take a single parameter s (a string)
  let mut s=s.bytes().peekable();                // Turn s into a peekable iterator
  while s.peek().is_some(){                      // While s is nonempty:
    for c in 65..91{                             //   For every c in range [65, 91) (uppercase alphabet):
      print!("{}",if Some(c)==s.peek().cloned(){ //     If the next character in s is the same as c:
        s.next();                                //       Advance the iterator
        c                                        //       Print c as a character
      } else {                                   //     Else:  
        32                                       //       Print a space
      } as char)                                 //
    }                                            //
    println!()                                   //   Print a newline
  }
}
\$\endgroup\$
0
\$\begingroup\$

Stax, 12 bytes

ü→Δe-Y─▲99╣w

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

{<!}    block tests if one value is >= another
)       use block to split input into partitions by testing adjacent pairs
m       map partitions using rest of the program and output
  zs    put a zero-length array under the partition in the stack
  F     for each letter in the array, run the rest of the program
    65- subtract 65 (ascii code for 'A')
    _&  set the specified index to the character, extending the array if necessary

Run this one

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

Two tied solutions:

Zsh, 71 bytes

for ((;#1;)){s=
for y ({A..Z})((#1==#y))&&s+=$y&&1=${1:1}||s+=\ 
<<<$s}

Try it online!

This uses straightforward comparison/ternary.

Zsh, 71 bytes

for ((;#1;)){s=
for y ({A..Z})s+=${${(M)1[1]%$y}:-\ }&&1=${1#$y}
<<<$s}

Try it online!

This is a bit more clever, appending to s either the matched letter or a space in one statement, then removing a letter if it matches from the front of $1.

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

Japt -R, 11 bytes

;ó< £BôkX ¸

Try it or run all test cases

;ó< £BôkX ¸     :Implicit input of string
 ó<             :Partition between characters where the first is < the second
    £           :Map each X
;    B          :  Uppercase alphabet
      ô         :  Split at characters that return falsey (empty string)
       kX       :    When the characters in X are removed
          ¸     :  Join with spaces
                :Implicit output joined with newlines
\$\endgroup\$
-1
\$\begingroup\$

Mathematica, 184 bytes

(t=Characters@#;s=Flatten@Table[Alphabet[],(l=Length)@t];q=1;For[i=1,i<=l@s,i++,If[s[[i]]!=t[[q]],s[[i]]=" ",q++];If[q>l@t,q--;t[[q]]=0]];StringRiffle[StringPartition[""<>s,26],"\n"])&
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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