Create a grid as close to a square as possible

10

Create a function or program that makes a grid as close to an square as possible

  • You will be given an integer N as input, whole numbers (1,2,3,25, etc)
  • The output must be a perfect rectangular grid of N letters as close to a square as possible
  • The (wannabe)square must consist of one of the the letters O or X as specified by user

Points:

  • Hardcoded to only O or X: +1
  • A param(0/1, true/false, something similar) to rotate output (like with 5 or 8): -10
  • Design the square (use both O and X in some sort of pattern): -5

A pattern is considered valid if it contains both types of characters (where x/y-axis >= 3) and the pattern stays the same when flipped horizontally or vertically (exchanging Xs with Os is allowed)

Examples

INPUT: 4         INPUT: 5       INPUT: 8              INPUT: 9
OO               OOOOO          XXXX                  XOX
OO                              XXXX                  OXO  
                                or rotated 90deg      XOX

Examples which aren't allowed (not same length row or columns)

BAD RESULT: 5a        BAD RESULT: 5b      BAD RESULT: 8
OOO                   OO                  OOO
OO                    OO                  OOO
                      O                   OO

If possible please provide an online example.

Martijn

Posted 2014-09-25T08:46:45.623

Reputation: 713

Is a function enough, or do you want a full program? – John Dvorak – 2014-09-25T08:56:44.567

" Design the square ... in case of 9 change the center" -- under which exact circumstances is the pattern not a checkerboard? Can you provide an example? – John Dvorak – 2014-09-25T08:59:52.920

re the edit: do I read correctly that I get three points for doing "xo"[i] instead of i? That doesn't seem worth it. In general, all of your rewards seem kinda low. – John Dvorak – 2014-09-25T09:01:20.093

"some sort of pattern" is kinda vague. Does it count if I replace the first 'x' with 'o'? – John Dvorak – 2014-09-25T09:02:12.697

Nice question. The only interesting bonus/penalty is the rotation one. Personally I would stick with one, hardcoded character (i.e. make the penalty the default) and eliminate all the bonuses / penalites except perhaps the rotation one. It's not a good idea to have too many bonuses or penalties. The important thing is to specify the main problem clearly. – Level River St – 2014-09-25T09:30:17.760

@steveverrill I don't consider them too many - just generally not worth it – John Dvorak – 2014-09-25T09:31:48.603

Wasn't sure about one of bonusses, changed it to the two now. I like the design one, a bit of creativity. – Martijn – 2014-09-25T09:32:29.820

I don't see any X in the examples. Really don't understand the X/O point. – edc65 – 2014-09-25T09:59:11.373

@edc65 I think the Pattern is meant like this: At least one of the characters in your output must be X and at least one must be O and your program must support the rotation-flag so that the pattern changes like you would rotate the grid – Falco – 2014-09-25T12:18:15.637

@Falco then put just a single X at top left, no change rotating (seriously, I'm going to try that) – edc65 – 2014-09-25T12:30:14.933

1 X amongst all O's isnt really a pattern is it? We're all smart people. – Martijn – 2014-09-25T12:38:05.050

@Martijn if it happens to be in the exact center, it's a valid pattern under the definition you have included. – John Dvorak – 2014-09-25T13:30:52.353

See, we're all smart ;) You're right. But one top left isn't – Martijn – 2014-09-25T13:36:04.017

Answers

6

CJam, 16 (31 - 10 - 5)

This takes two integers are input, first one being 0 or 1 for direction and second one being the number of O or X in the grid.

It prints an alternate O and X.

:X"OX"*X<\Xmqi){(_X\%}g_X\/?/N*

This is just the function body, to try it out add l~ in front of the code like:

l~:X"OX"*X<\Xmqi){(_X\%}g_X\/?/N*

and give input like

0 10

to get output like

OXOXO
XOXOX

or input like

1 10

for

OX
OX
OX
OX
OX

Try it online here


How it works:

l~                                 "Put the two input integers to stack";
  :X                               "Assign the number of cells to X";
    "OX"*                          "Take string "OX" and repeat it X times";
         X<                        "Slice it to take only first X characters";
           \                       "Swap top two stack elements, now string is at bottom";
            Xmqi)                  "Take square root of X, ceil it and put on stack";
                 {(_X\%}g          "Keep decrementing until it is perfectly divisible by X";
                         _X\/      "Copy it, divide X by that and put it on stack";
                             ?     "Based on first input integer, take either of numbers";
                              /    "Divide the XOXO string that many times";
                               N*  "Join the string parts with a new line";

Example run:

l~ed:X"OX"*edX<ed\edXmqi)ed{(_X\%}ged_edXed\ed/ed?ed/edN*ed

#INPUT:
1 10

#OUTPUT:
Stack: [1 10]

Stack: [1 "OXOXOXOXOXOXOXOXOXOX"]

Stack: [1 "OXOXOXOXOX"]

Stack: ["OXOXOXOXOX" 1]

Stack: ["OXOXOXOXOX" 1 4]

Stack: ["OXOXOXOXOX" 1 2]

Stack: ["OXOXOXOXOX" 1 2 2]

Stack: ["OXOXOXOXOX" 1 2 2 10]

Stack: ["OXOXOXOXOX" 1 2 10 2]

Stack: ["OXOXOXOXOX" 1 2 5]

Stack: ["OXOXOXOXOX" 2]

Stack: [["OX" "OX" "OX" "OX" "OX"]]

Stack: ["OX
OX
OX
OX
OX"]

OX
OX
OX
OX
OX

Optimizer

Posted 2014-09-25T08:46:45.623

Reputation: 25 836

3

APL (36 - 5 - 10 = 21)

{'OX'⍴⍨⍺⌽⊃∆/⍨⍵=×/¨∆←∆[⍋|-/¨∆←,⍳2/⍵]}

The left argument is rotation, the right argument is the size. It also uses a simple pattern (it just alternates 'X' and 'O').

      0{'OX'⍴⍨⍺⌽⊃∆/⍨⍵=×/¨∆←∆[⍋|-/¨∆←,⍳2/⍵]}¨4 5 8 9
 OX  OXOXO  OXOX  OXO 
 OX         OXOX  XOX 
                  OXO 
      1{'OX'⍴⍨⍺⌽⊃∆/⍨⍵=×/¨∆←∆[⍋|-/¨∆←,⍳2/⍵]}¨4 5 8 9
 OX  O  OX  OXO 
 OX  X  OX  XOX 
     O  OX  OXO 
     X  OX      
     O       

Explanation:

  • ∆←,⍳2/⍵: generate all possible pairs of numbers from 1 to and store in .
  • ∆←∆[⍋|-/¨∆...]: sort ascending in the absolute difference of the two numbers in each pair, and store the result back in .
  • ⊃∆/⍨⍵=×/¨∆: for each pair, multiply the numbers together. Select only those pairs that multiply to , and take the first one that matches (which is the 'most square' because of the sort).
  • ⍺⌽: rotate the list of lengths (which has 2 elements) by .
  • 'OX'⍴⍨: create a matrix of that size, and fill it with alternating O and X.

marinus

Posted 2014-09-25T08:46:45.623

Reputation: 30 224

2

Python, 79 75 (no bonuses)

The bonuses seem tricky, so here is a pretty simple Python function:

def f(N):c=max(x*((x*x<=N)>N%x)for x in range(1,N+1));print(N/c*'O'+'\n')*c

Emil

Posted 2014-09-25T08:46:45.623

Reputation: 1 438

Online example for the interested: http://repl.it/Zq9

– Martijn – 2014-09-25T09:50:10.283

1Did you change this after testing? I tried this and it does not work, for example f(8) gave me one column of 8 Os, which is incorrect. – marinus – 2014-09-25T13:58:14.697

@marinus: I did test it but seem to have copied a wrong version. There was a > where there should have been a <. It's fixed now. Thanks for the note! – Emil – 2014-09-25T14:08:56.620

2

Haskell, 59 characters

r=replicate
f n=[r x$r y '0'|x<-[1..n],y<-[1..x],x*y==n]!!0

John Dvorak

Posted 2014-09-25T08:46:45.623

Reputation: 9 048

2

JavaScript (E6) 84 (83+1) or 101 (116-10-5)

Pattern + rotation (parameter f, 0 or 1) - bonus 15

F=(n,f)=>{
  for(r=x=0;y=n/++x|0,x<=y;)x*y-n?0:z=f?x:y;
  for(o='';n;)o+=(n--%z?'':(r^=1,c='\n'))+'OX'[r^(c^=1)];
  alert(o)
}

No pattern, no rotation - penalty 1

F=n=>{
  for(x=0;y=n/++x|0,x<=y;)x*y-n?0:z=y;
  alert(('O'.repeat(z)+'\n').repeat(n/z));
}

Test In FireFox/FireBug console

F(30,0)

OXOXOX
XOXOXO
OXOXOX
XOXOXO
OXOXOX

F(30,1)

OXOXO
XOXOX
OXOXO
XOXOX
OXOXO
XOXOX

edc65

Posted 2014-09-25T08:46:45.623

Reputation: 31 086

2

CJam, 25 22 21 (31 - 10)

This is a function body. If you want a complete program, add riri to the front. If you want to use it as a code block, surround it in {}. Test it on cjam.aditsu.net.

It takes input as two integer arguments: the switch for whether the rectangle is vertical (any non-zero value) or horizontal (zero), and the number of Os to use.

:Xmqi){(_X\%}g_X\/@{\}{}?'O*N+*

Explanation

:X "Assign the top item on the stack (the second input) to variable X";
mq "Take its square root";
i  "Convert to integer (round)";
)  "Increment it";

{  "Start code block";
  (  "Decrement";
  _X "Duplicate top item on stack; push X to the stack";
  \% "Swap top 2 items and take division remainder";
}g "Loop until top item on stack is 0; pop condition after checking it";

_X "Duplicate top item on stack; push X to the stack";
\/ "Swap top 2 items and divide";

"OMIT THIS BIT TO GET A 25-CHAR FUNCTION WITHOUT THE 10PT BONUS";
 @  "Rotate top 3 items on stack";
 {\}"Code block 1: swap top two items";
 {} "Code block 2: do nothing";
 ?  "If top item of stack is 0, run code block 1, otherwise run code block 2";

'O "Push the character O to the stack";
*  "Repeat it N times, where N is the second item from the top of the stack (O is first)";
N+ "Push a new line and concatenate it with the string on the top of the stack";
*  "Repeat the string N times";

user16402

Posted 2014-09-25T08:46:45.623

Reputation:

1Decrement should be quite faster for big numbers, without loss in byte count – edc65 – 2014-09-25T10:41:59.293

1Who downvoted? Why? – None – 2014-09-25T12:58:11.487

2I can only guess it's because someone doesn't consider CJam a real language – John Dvorak – 2014-09-25T13:21:42.927

Your explanation is kinda broken. Are you currently editing? – John Dvorak – 2014-09-25T13:31:53.907

@JanDvorak Yes, I was halfway through editing it and accidentally pressed Tab and Enter. It's fixed now. – None – 2014-09-25T13:32:44.807

1

APL (Dyalog Unicode), 30 - 15 = 15 bytesSBCS

Anonymous infix lambda. Takes N as right argument and param as left argument. Rectangles will either have stripes of X and O or be chequered.

{⍉⍣⍺⍴∘'XO'⊃∘c⌈.5×≢c←⍸⍵=∘.×⍨⍳⍵}

Try it online!

{} "dfn"; is left argument (param), is right argument (N):

⍳⍵ɩndices 1…N

∘.×⍨ multiplication table of that

⍵= mask where N is equal to that

ɩndices of true values in the mask

c← store that in c (for candidates)

 tally the candidates

.5× one half multiplied by that

 ceiling (round up)

⊃∘c pick that element from c

⍴∘'XO' use that to cyclically reshape "XO"

⍉⍣⍺ transpose if param

Adám

Posted 2014-09-25T08:46:45.623

Reputation: 37 779

1

05AB1E (legacy), score: 7 (22 bytes - 15 bonus)

„OXI∍¹tï[D¹sÖ#<}äIiø}»

Try it online or verify some more test cases.

Takes the inputs N first, then the boolean (0/1) whether it should rotate or not.

Uses the Python legacy version of 05AB1E since zip with a string-list implicitly flattens and joins the characters, unlike the newer Elixir rewrite version of 05AB1E.

Explanation:

„OX         # Push string "OX"
   I∍       # Extend it to a size equal to the first input
            #  i.e. 9 → "OXOXOXOXO"
            #  i.e. 10 → "OXOXOXOXOX"
¹t          # Take the first input again, and square-root it
            #  i.e. 9 → 3.0
            #  i.e. 10 → 3.1622776601683795
  ï         # Then cast it to an integer, removing any decimal digits
            #  i.e. 3.0 → 3
            #  i.e. 3.1622776601683795 → 3
   [        # Start an infinite loop:
    D       #  Duplicate the integer
     ¹sÖ    #  Check if the first input is evenly divisible by that integer
            #   i.e. 9 and 3 → 1 (truthy)
            #   i.e. 10 and 3 → 0 (falsey)
        #   #  And if it is: stop the infinite loop
    <       #  If not: decrease the integer by 1
            #   i.e. 3 → 2
   }        # After the infinite loop:
ä           # Divide the string into that amount of equal sized parts
            #  i.e. "OXOXOXOXO" and 3 → ["OXO","XOX","OXO"]
            #  i.e. "OXOXOXOXOX" and 2 → ["OXOXO","XOXOX"]
 Ii }       # If the second input is truthy:
   ø        #  Zip/transpose; swapping rows/columns of the strings
            #   i.e. ["OXOXO","XOXOX"] → ["OX","XO","OX","XO","OX"]
»           # And finally join the strings in the array by newlines
            #  i.e. ["OXO","XOX","OXO"] → "OXO\nXOX\nOXO"
            #  i.e. ["OX","XO","OX","XO","OX"] → "OX\nXO\nOX\nXO\nOX"
            # (and output the result implicitly)

Kevin Cruijssen

Posted 2014-09-25T08:46:45.623

Reputation: 67 575

1

Ruby, 74

f=->n{w=(1..n).min_by{|z|n%z>0?n:(n/z-n/(n/z))**2};$><<("X"*w+"\n")*(n/w)}

Explanation

  • Input is taken as arguments to a lambda. It expects an Integer.
  • Check if n (the input) is divisible by every integer from 1 to n.
    • If it is, calculate the difference between the length and width.
    • If it is not, return a large number (n).
  • Take the smallest of length-width differences to best resemble a square.
  • Use (the overly concise) String#* method to "draw" the square.

britishtea

Posted 2014-09-25T08:46:45.623

Reputation: 1 189

Why was I downvoted? Does my answer contain a bug? – britishtea – 2014-09-27T18:57:11.100

You have a typo. The last word should be "square" and you have "sqaure". (I am not the downvoter, I'm pointing this mistake). – Ismael Miguel – 2014-09-27T22:26:25.653

0

Petit Computer BASIC, 72 bytes

INPUT N,S$FOR I=1TO SQR(N)IF N%I<1THEN M=I
NEXT
?(S$*M+" "*(32-M))*(N/M)

12Me21

Posted 2014-09-25T08:46:45.623

Reputation: 6 110

0

J, 32 bytes - 15 = 17 bytes

'XO'$~[|.](%,])i.@]{~0 i:~i.@]|]

Try it online!

The rotation is controlled by a 0/1 flag taken as the left argument

Jonah

Posted 2014-09-25T08:46:45.623

Reputation: 8 729

0

Retina 0.8.2, 66 bytes + 1 byte penalty = 67

.+
$*X
((^|\3)(X(?(3)\3)))+(\3)*$
$3 $3$#4$*X
X(?=X* (X+))| X+
$1¶

Try it online! Explanation:

.+
$*X

Convert the input to a string of Xs.

((^|\3)(X(?(3)\3)))+(\3)*$

The first pass of the outer capture matches the start of the string while on subsequent passes the previous value of the inner capture is matched. The inner capture is then incremented and matched. The upshot of this is that the amount of string consumed by the outer capture is the square of the inner capture, which therefore cannot exceed the square root of the input. Meanwhile the subsequent repetition ensures that the inner capture is a factor of the length of the string.

$3 $3$#4$*X

Save the discovered factor and calculate the other divisor by adding on the number of subsequent repetitions.

X(?=X* (X+))| X+
$1¶

Rearrange the factors into a rectangle.

Neil

Posted 2014-09-25T08:46:45.623

Reputation: 95 035

0

Charcoal, 33 bytes - 10 - 5 = 18

Nθ≔⌊Φ⊕θ¬∨‹×ιιθ﹪θιηE÷θη⭆η§XO⁺ιλ¿N⟲

Try it online! Link is to verbose version of code. Explanation:

Nθ

Input N.

≔⌊Φ⊕θ¬∨‹×ιιθ﹪θιη

Take the range 0..N, keep only the numbers whose squares are not less than N and divide N, and take the minimum of those numbers.

E÷θη⭆η§XO⁺ιλ

Use the discovered factor to output a rectangle of the appropriate width and height using a chequerboard pattern. (This should be UOη÷θηXO¶OX for a 1-byte saving but that's buggy right now.)

¿N⟲

If the second input is nonzero then rotate the output. (If requiring the second input to be 0 or 2 is acceptable, then this could be ⟲N for a 1-byte saving.)

Neil

Posted 2014-09-25T08:46:45.623

Reputation: 95 035

0

GolfScript 26 (41 - 10 - 5)

:x),1>{x\%!},.,2/=.x\/@{\}*'X'*n+*1>'O'\+

Expects two parameters to be on the stack:

  • 0 for normal or 1 for transposed
  • the n value

The pattern is that the board is full of Xs and the top left corner is an O. Needless to say, this pattern is maintained when transposing the board.

Demo: regular, transposed

Cristian Lupascu

Posted 2014-09-25T08:46:45.623

Reputation: 8 369

0

Mathematica, 71 chars

f@n_:=#<>"\n"&/@Array["O"&,{#,n/#}&[#[[⌊Length@#/2⌋]]&@Divisors@n]]<>""

alephalpha

Posted 2014-09-25T08:46:45.623

Reputation: 23 988