Simulate rotating a board

14

1

Introduction

You're playing a matching game, in which coins are inserted at the top and fall to the bottom (onto the top coin) due to gravity.

So this

O <- inserting this coin

OO O
OOOOO

will become this

O
OO O
OOOOO

Now imagine someone rotates the board clockwise. The following will happen:

1. The board is rotated

OOO
OO
O
OO
O

2. Coins fall down due to gravity

O
O
OO
OO
OOO

Your task

Your task is to simulate the rotation of the board by writing a program or a function. For the sake of simplicity we're only dealing with one kind of coin (it's not a too exciting matching game, is it…). You can assume that gravity is applied only after the rotation is complete. The board is rotated clockwise.

Input

The input is going to be a string, which contains 3 types of characters:

  • O (capital o) OR 0 (zero) - a coin (you decide which one your solution supports)
  • (space) - an empty field
  • \n (new line) - end of row

The input represents the state of the board. You can assume, the input is well formed and contains a valid state of the board (no coins are floating). The input can be a function parameter, or can be read from the standard input or from a file.

Output

The output is the new state of the board after rotation. The output contains the same 3 types of characters as the input. The output can be returned from your function or can be written to the standard output or to a file.

Sample

Input1:

O
OO O
OOOOO

Output1:

O
O
OO
OO
OOO

Input2:

O O
O O

Output2:

OO
OO

You can use any language and the standard library of the chosen language. Shortest program in bytes wins.

David Frank

Posted 2014-06-26T14:14:19.013

Reputation: 1 933

Are the shorter lines padded with trailing spaces? – Ventero – 2014-06-26T15:05:22.060

If you need so then yes. – David Frank – 2014-06-26T15:08:56.763

What are the requirements for the board size? Can I choose a reasonable maximum size, or does the application/function need to work for all possible sizes? – Fors – 2014-06-26T16:16:05.473

You can assume that the maximum size of the board is 50x50 – David Frank – 2014-06-26T16:17:50.083

Does any part of the task involve matching? – user2357112 supports Monica – 2014-06-26T18:19:17.040

@user2357112 no – David Frank – 2014-06-26T18:22:10.420

2If gravity is applied after rotation, how does Input2 become Output2? I would have thought it would drop the top coins down but not horizontally? – Matt – 2014-06-26T23:37:44.053

I think the correct output2 should be two piles of two coins separated by one empty column. – justhalf – 2014-06-27T02:34:11.267

2@Matt Note, that there are no empty rows in Input2, nor in Output2 (SE displays margin between the rows). – David Frank – 2014-06-27T10:35:59.883

@justhalf You can assume, the input is well formed and contains a valid state of the board (no coins are floating) It's actually impossible to get a blank column sandwiched between non-blank columns – Cruncher – 2014-06-27T15:33:04.310

Yes, I thought there was an empty row in the input. – justhalf – 2014-06-27T16:09:02.547

@David Frank, you are right, makes sense now! The empty column along with what looked like the empty row was confusing (to me!). – Matt – 2014-06-29T23:12:31.227

Answers

16

GolfScript, 14 12 characters

' '-n%zip$n*

Input must be given on STDIN, the character for coins can be any non-whitespace characters. Try here. Thanks to Peter for pointing out a two character reduction.

Howard

Posted 2014-06-26T14:14:19.013

Reputation: 23 109

Oh, what I wouldn't give for a transpose in Ruby that can handle arrays with different lengths ... – Ventero – 2014-06-26T15:07:19.600

@Ventero Most of the times I use this hacky version: ([nil]*a.map(&:size).max).zip(*a). Not good for golfing though. – Howard – 2014-06-26T15:28:07.270

You can save 2 chars: since the longest lines always end up at the bottom, you can replace -1% with $. – Peter Taylor – 2014-06-26T15:59:48.963

@PeterTaylor You're right - we can save to chars. Thank you. – Howard – 2014-06-26T16:12:35.813

The CJam translation has 9 characters, but it's way too similar so I hesitate to post it :p – aditsu quit because SE is EVIL – 2014-06-26T16:54:13.423

@aditsu, you designed CJam, didn't you? Why didn't you include a one-character alias for ' '? – Peter Taylor – 2014-06-26T17:47:13.370

1@PeterTaylor Well, I did include a one-character alias for " ". – aditsu quit because SE is EVIL – 2014-06-26T18:01:04.920

6

Ruby 2.0, 59 characters

puts$<.map(&:chars).reverse.transpose.sort[1,50].map &:join

Input via stdin, assumes lines all have the same length. This is probably much longer than necessary. But at least it's readable ...

Ventero

Posted 2014-06-26T14:14:19.013

Reputation: 9 842

I think you can use $<.map instead. – Howard – 2014-06-26T15:08:04.943

@Howard That's one thing I always forget. Thanks! – Ventero – 2014-06-26T15:09:17.440

1what is [1,50] doing there? – Not that Charles – 2014-06-26T21:02:43.673

1@Charles It skips the first row, which contains all the newlines from the input. David mentioned in a comment that 50x50 is the maximum possible size, so instead of selecting all but the first row (1..-1), I just select 50 rows starting with the second one (1,50). – Ventero – 2014-06-26T21:04:57.490

@Ventero got it. cool. thanks! – Not that Charles – 2014-06-26T21:11:41.863

6

Javascript (E6) 103

First try, just matrix operations. Each row in input string need to be padded.
Quite wordy.

R=t=>(x=t.split('\n').reverse().map(x=>[...x].sort()),x.map((c,i)=>x.map(r=>r[i]).join('')).join('\n'))

Pseudo code

  1. string -> array of rows
  2. up/down reverse array
  3. each row -> char array
  4. sort each row (coins 'fall' to right)
  5. transpose
  6. each char array in a row -> a string
  7. join array -> single string

edc65

Posted 2014-06-26T14:14:19.013

Reputation: 31 086

Oh wow, sorting is smart (+1)! Mind if I steal it? – seequ – 2014-06-26T18:46:01.933

I've never seen the syntax [...x] before. What is it called? – ComFreek – 2014-06-26T21:12:09.320

2@ComFreak it's called spread [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator] – edc65 – 2014-06-26T21:17:39.660

2

@edc65 You broke your own link with brackets. Here is the correct link

– Chris Cirefice – 2014-06-27T17:42:55.887

3

J - 49 31 24 bytes

I think there might be unnecessary rotations in there, but otherwise it works fine. It's a function that takes the input as specified, coins being O. No trailing whitespace is required in the input.

New version, inspired by edc65's Javascript answer:

f=:[:|."1@|:[:/:~"1,;._2

Explanation:

f=:[:|."1@|:[:/:~"1,;._2
                   ,;._2 Split the string at every fret, which is the last character in the string (newline).
              /:~"1      Sort every row separately.
     |."1@|:             Rotate the array clockwise.

Old version:

f=:[:|:((#~=&' '),=&'O'#])"1@|:@(|."1@|:)@(,;._2)

Explanation:

f=:[:|:((#~=&' '),=&'O'#])"1@|:@(|."1@|:)@(,;._2)
                                          (,;._2) Split the string at every fret, which is the last character in the string (newline).
                                (|."1@|:)@        Rotate the array clockwise.
                             |:@                  Reverse the axes (columns become rows and vice-versa).
       ((#~=&' '),=&'O'#])"1                      Function that applies the "gravity"
                          "1                       Apply to every row separately:
                  =&'O'#]                           Get the O's in the row.
       (#~=&' ')                                    Get the spaces in the row.
                ,                                   Join them, spaces come first.
  [:|:                                            Reverse axes again.

Examples (note that multiline strings start with 0 : 0 and end withh a bracket):

   f 0 : 0
O
OO O
OOOOO
) NB. output starts now
O  
O  
OO 
OO 
OOO
   f 0 : 0
O O
O O
) NB. Output starts now.

OO
OO

seequ

Posted 2014-06-26T14:14:19.013

Reputation: 1 714

If you can, sort before rotate – edc65 – 2014-06-26T19:07:18.617

@edc65 You're a smart man. – seequ – 2014-06-26T19:14:39.473

2

Python 2 (69) (79)

for c in sorted(zip(*raw_input().split("\\n"))):print''.join(c[::-1])

Takes input padded with spaces so all lines have equal length. The split creates an arrat of each line. The zip effectively transposes the array. Then, the sorted sorts tuples in lexicographic order, causing all coins to fall to the bottom. Finally, we print each line, turning it back into a string, though we must reverse it first. Doing print'O'*c.count('O') is equivalent and uses the same number of characters.

Example run:

>> O    \nOO O \nOOOOO
O
O
OO
OO
OOO

xnor

Posted 2014-06-26T14:14:19.013

Reputation: 115 687

2

Haskell — 86

Just learning, so I'm sure this can be improved.

import Data.List
c=putStr.unlines.filter(/="").sort.map(filter(/=' ')).transpose.lines

Sample Input:

let a = "O    \nOO O \nOOOOO"
let b = " O O \n O O "
c a
c b

Sample Output:

O
O
OO
OO
OOO

OO
OO

O-I

Posted 2014-06-26T14:14:19.013

Reputation: 759

1

C, 167 119 bytes

This shorter version is (unfortunately?) much clearer than the original too.

m;j;b[99];r;main(){while(j=getchar()+1)j-11?m+=j-33&&++b[r]>m:++r;for(j=r;m+1;putchar(j--?m<b[j]?79:32:(j=r,m--,10)));}

j_random_hacker

Posted 2014-06-26T14:14:19.013

Reputation: 31

0

Racket: 130

(let l((a'()))(let((b(sort(string->list(read-line))char<?)))(if
(null? b)(apply map(λ x(map display x)(newline))a)(l(cons b a)))))

It requires you pad with spaces so the lines are equal lemgth.

Sylwester

Posted 2014-06-26T14:14:19.013

Reputation: 3 678

0

C# - 209 174 bytes

Right, I have to try this Code golf at some point I reckon. Created a function (r) that rotates the board and prints it. I guess I'm cheating a little when I am printing my char array, but if you cannot figure out why you shouldn't be mad :)

Thanks to ProgramFOX for the tips :)

void r(string s){int x=s.IndexOf('\n'),j,i=-1,k,z=x+1;var y=new char[x*x+x];for(;++i<x;y[z*(i+1)-1]='\n')for(k=j=x;j>0;)if(s[i*z+--j]=='0')y[k--*z-i-2]='0';Console.Write(y);}

Cheat

new char[x*x+x] fills the array with '\0' and not ' '

WozzeC

Posted 2014-06-26T14:14:19.013

Reputation: 201

1Removing the newlines and removing the space between char[] and y will reduce your character count to 192 characters. Also, it is not really necessary to provide the keyword static when posting an answer here. Removing it will reduce your character count to 185 characters. – ProgramFOX – 2014-06-27T16:20:49.117

I was also able to remove 'ref ' which was forgotten there since an earlier try. – WozzeC – 2014-06-27T19:38:11.153