21
\$\begingroup\$

Introduction

You may know and love your normal unit circle. But mathematicans are crazy and thus they have abstracted the concept to any point that satisfies x*x+y*y=1. Because Cryptographers1 are also weird, they love finite fields and sometimes finite rings (it is not like they have much choice though), so let's combine this!

The Challenge

Input

A positive integer larger than one in your favorite encoding. Let's call this number n.

Output

You will output the "picture" (which consists of n times n characters) of the unit circle modulo the input integer as ASCII-Art using "X" (upper-case latin X) and " " (a space). Trailing spaces and newlines are allowed.

More Details

You have to span a coordinate system from bottom-left to top-right. Whenever a point fulfills the circle equation, place an X at the position, otherwise place a space.

The condition for a point to be considered part of the circle border is:
mod(x*x+y*y,n)==1.

Here a quick illustration of the coordinate-system:

(0,4)(1,4)(2,4)(3,4)(4,4)
(0,3)(1,3)(2,3)(3,3)(4,3)
(0,2)(1,2)(2,2)(3,2)(4,2)
(0,1)(1,1)(2,1)(3,1)(4,1)
(0,0)(1,0)(2,0)(3,0)(4,0)

If it helps you, you may also invert the direction of any of the axes, but the examples assume this orientation.

Who wins?

This is so the shortest code in byte wins! Only the default I/O methods are allowed and all standard loopholes are banned.

Examples

Input: 2

X 
 X

Input: 3

X  
X  
 XX

Input: 5

X    
     
     
X    
 X  X

Input: 7

X      
  X  X 
       
       
  X  X 
X      
 X    X

Input: 11

X          
           
     XX    
           
   X    X  
   X    X  
           
     XX    
           
X          
 X        X

Input: 42

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                 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                             X     
       X                           X      
            X                 X           
                                          
                                          
         X                       X        
X                                         
 X           X               X           X

1 I suggest you take a look at my profile if you're wondering here.

\$\endgroup\$
5
  • \$\begingroup\$ Looks much better if you use the domain [0,n] in my opinion. Here is an example with input 42. \$\endgroup\$
    – R. Kap
    Apr 1, 2017 at 19:11
  • \$\begingroup\$ By "standard I/O" do you mean default I/O methods, or do you mean actual STDIN/STDOUT? I'm assuming the former, but I think someone below has interpreted it as the latter. \$\endgroup\$ Apr 2, 2017 at 0:02
  • \$\begingroup\$ @ØrjanJohansen indeed the former. \$\endgroup\$
    – SEJPM
    Apr 2, 2017 at 0:07
  • \$\begingroup\$ Are preceding newlines allowed? \$\endgroup\$
    – fergusq
    Apr 2, 2017 at 9:13
  • \$\begingroup\$ @fergusq as they would (drastically) alter the output figure in a visible way, no. \$\endgroup\$
    – SEJPM
    Apr 2, 2017 at 9:23

18 Answers 18

6
\$\begingroup\$

Bash + GNU Utilities, 59

x={0..$[$1-1]}d*
eval echo $x$x+$1%1-0r^56*32+P|dc|fold -$1

Input n given as a command-line parameter. The y-axis is inverted.

Try it online.

\$\endgroup\$
4
\$\begingroup\$

Octave, 45 44 bytes

@(n)[(mod((x=(0:n-1).^2)+x',n)==1)*56+32,'']

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ This also works: @(n)[(mod((x=(0:n-1).^2)+x',n)==1)*88,'']. In certain systems Octave treats character 0 as a space \$\endgroup\$
    – Luis Mendo
    Apr 2, 2017 at 2:35
3
\$\begingroup\$

Haskell, 68 bytes

f n|r<-[0..n-1]=unlines[[last$' ':['X'|mod(x*x+y*y)n==1]|y<-r]|x<-r]

Try it online! The y-axis is flipped. Usage: f 42 returns a newline delimited string.

This is a nested list comprehension where both x and y are drawn from the range [0..n-1]. last$' ':['X'|mod(x*x+y*y)n==1] is a shorter form of if mod(x*x+y*y)n==1 then 'X' else ' '. The list comprehension evaluates to a list of strings which is turned into a single newline separated string by unlines.

\$\endgroup\$
3
\$\begingroup\$

Mathematica, 56 48 bytes

Edit: Thanks to Greg Martin and Martin Ender for saving 8 bytes.

Grid@Array[If[Mod[#^2+#2^2,x]==1,X]&,{x=#,#},0]&

Original solution:

Grid@Table[If[Tr[{i-1,j-1}^2]~Mod~#==1,X,],{i,#},{j,#}]&
\$\endgroup\$
5
  • \$\begingroup\$ Amusing remark: you don't need the comma after X :) \$\endgroup\$ Apr 1, 2017 at 19:31
  • 1
    \$\begingroup\$ I think you're better off with Array and Norm: Grid@Array[If[Mod[Norm@{##}^2,x]==1,X]&,{x=#,#},0]& \$\endgroup\$ Apr 1, 2017 at 19:34
  • 2
    \$\begingroup\$ Still overthinking it... #^2+#2^2 is shortest. \$\endgroup\$ Apr 1, 2017 at 19:45
  • \$\begingroup\$ @GregMartin So if the first argument to If is neither True or False, you need the fourth argument or it remains unevaluated, but If[False,_] returns Null. Weird. \$\endgroup\$
    – user61980
    Apr 3, 2017 at 19:00
  • \$\begingroup\$ @MartinEnder I initially tried Array but didn't think to set the argument to a variable. \$\endgroup\$
    – user61980
    Apr 3, 2017 at 19:01
2
\$\begingroup\$

CJam, 23 bytes

ri:X,2f#_ff{+X%(S'X?}N*

Try it online!

ri:X    e# Read input, convert to integer, store in X.
,       e# Turn into range [0 1 ... X-1].
2f#     e# Square each value in the range.
_ff{    e# 2D map over all pairs from that list.
  +     e#   Add the two values in the current pair.
  X%    e#   Take the sum modulo X.
  (     e#   Decrement, so that x^2+y^2==1 becomes 0 (falsy) and everything
        e#   else becomes truthy.
  S'X?  e#   Select space of 'X' accordingly.
}
N*      e# Join rows with linefeeds.
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 81 bytes

f=
n=>[...Array(n)].map((_,x,a)=>a.map((_,y)=>(x*x+y*y)%n-1?` `:`X`).join``).join`
`
<input type=number oninput=o.textContent=f(+this.value)><pre id=o>

The Y-axis is the reverse of the OP.

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

Röda, 74 bytes

f n{seq n-1,0|{|y|seq 0,n-1|{|x|["X"]if[(x^2+y^2)%n=1]else[" "]}_;["
"]}_}

Try it online!

Ungolfed:

function f(n) {
    seq(n-1, 0) | for y do
        seq(0, n-1) | for x do
            if [ (x^2 + y^2) % n = 1 ] do
                push("X")
            else
                push(" ")
            done
        done
        print("")
    done
}
\$\endgroup\$
2
\$\begingroup\$

Python 3, 87 83 bytes

lambda n:"\n".join("".join(" X"[(y*y+x*x)%n==1]for x in range(n))for y in range(n))

Try it online!

The y-axis is inverted

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

Jelly, 14 13 bytes

R²+þ`%=1ị⁾X Y

The x-axis is inverted.

Try it online!

How it works

R²+þ`%=1ị⁾X Y  Main link. Argument: n

R              Range; yield [1, ..., n].
 ²             Square; yield [1², ..., n²].
  +þ`          Self table addition; compute x+y for all x and y in [1², ..., n²],
               grouping by the values of y.
     %         Take all sums modulo n.
      =1       Compare them with 1, yielding 1 or 0.
        ị⁾X    Index into "X ".
            Y  Separate by linefeeds.
\$\endgroup\$
1
\$\begingroup\$

dc, 79 bytes

?dsRsQ[88P]sl[32P]sH[0sM[lM2^lR2^+lQ%d1=l1!=HlM1+dsMlQ>c]dscx10PlR1-dsR0<S]dsSx

The y-axis is inverted whereas the x-axis is not.

Try it online!

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

Python 3, (102 98 95 bytes)

y-axis inverted

n=int(input());r=range(n);p=print
for i in r:
 for j in r:p(end=' 'if(i*i+j*j)%n-1else'X')
 p()

Try it online!

  • saved 4 bytes: omitted variable c in c=' 'if(ii+jj)%n-1else'X'
  • saved 3 bytes: Thanks to ovs (modified print statement)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ p(end=' 'if(i*i+j*j)%n-1else'X') for 95 bytes \$\endgroup\$
    – ovs
    Apr 2, 2017 at 10:15
1
\$\begingroup\$

Lithp, 125 bytes

#N::((join(map(seq(- N 1)0)(scope #Y::((join(map(seq 0(- N 1))(scope #X::
((?(== 1(@(+(* X X)(* Y Y))N))"X" " "))))""))))"\n")

Linebreak for readability.

Try it online!

Not the shortest. I think I need some sort of shorthand module. See the Try it Online link for further explanation, ungolfed version, and some tests. For best results, expand the output window to see more.

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

Python 3, 82 bytes

f=lambda n,k=0:k<n>f(n,k+1)!=print(''.join(' X'[(k*k+j*j)%n==1]for j in range(n)))

Try it online!

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

GNU APL, 41 chars, 59 bytes

Reads an integer and displays the circle.

N←⎕◊⌽{(⍵+1)⊃' ' 'X'}¨{1=(N|(+/⍵*2))}¨⍳N N

Ungolfed

N←⎕
⌽                           ⍝ flip the X axis so 0,0 is bottom left
{
    (⍵+1) ⊃ ' ' 'X'         ⍝ substitute space for 0, X for 1
} ¨ {
    1=(N|(+/⍵*2))           ⍝ mod(x*x+y*y, 1)==1
} ¨ ⍳N N                    ⍝ generate an NxN grid of coordinates
\$\endgroup\$
1
\$\begingroup\$

MATL, 13 bytes

:qU&+G\1=88*c

Origin is at top left. So the output is flipped upside down compared with the examples in the challenge.

Try at MATL online!

Explanation

:      % Input n implicitly. Push [1 2 ... n]
q      % Subtract one (element-wise)
U      % Square (element-wise)
&+     % Matrix of pairwise sums
G      % Push n
\      % Modulo
1=     % Equal to 1? (element-wise)
88*    % Multiply by 88 (ASCII code of 'X')
c      % Convert to char. Char 0 will be displayed as a space
       % Display implicitly
\$\endgroup\$
0
\$\begingroup\$

Haskell, 115 bytes

n#(a,b)|mod(a*a+b*b)n==1='X'|1>0=' '
m n=map(n#)<$>zipWith(zipWith(,))(replicate n[0..n-1])(replicate n<$>[0..n-1])

The y axis is inverted.

Try it online!

All those parentheses are kind of annoying me...

Explanation

n#(a,b)|mod(a*a+b*b)n==1='X'|1>0=' '
n#(a,b)                                 --Operator #, takes a number n and a tuple (a,b)
       |mod(a*a+b*b)n==1                --Test if the mod equals 1
                        ='X'            --If so, return 'X'
                            |1>0=' '    --Otherwise, return ' '

m n=map(n#)<$>zipWith(zipWith(,))(replicate n[0..n-1])(replicate n<$>[0..n-1])
m n=                                                                           --Make a new function m with argument n
                                 (replicate n[0..n-1])                         --Make a list of [[0,1,2,3..n-1],[0,1,2,3..n-1],(n times)]
                                                      (replicate n<$>[0..n-1]) --Make a list of [[0,0,0(n times)],[1,1,1(n times)]..[n-1,n-1,n-1(n times)]
              zipWith(zipWith(,))                                              --Combine them into a list of list of tuples
    map(n#)<$>                                                                 --Apply the # operator to every tuple in the list with the argument n
\$\endgroup\$
4
  • \$\begingroup\$ You can replace the last map with a <$>, right? \$\endgroup\$
    – k_g
    Apr 1, 2017 at 23:20
  • \$\begingroup\$ Unless I'm misinterpreting the question rules, I don't think you need all that I/O - golfing I/O on PPCG has special defaults to allow as many languages as possible to participate. For example, your main function can take an integer argument and return a string. \$\endgroup\$ Apr 2, 2017 at 0:07
  • \$\begingroup\$ @k_g yes thank you \$\endgroup\$ Apr 2, 2017 at 0:43
  • \$\begingroup\$ @ØrjanJohansen duly noted :) \$\endgroup\$ Apr 2, 2017 at 0:44
0
\$\begingroup\$

J, 20 bytes

' x'{~1=[|+/~@:*:@i.

Try it online!

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

GolfScript, 34 bytes

~:c,{.*}%:a{:b;a{b+c%1=' x'=}%}%n*

Try it online!

I really don't like using variables...

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