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

| improve this question | | | | |
\$\endgroup\$
  • \$\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 '17 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\$ – Ørjan Johansen Apr 2 '17 at 0:02
  • \$\begingroup\$ @ØrjanJohansen indeed the former. \$\endgroup\$ – SEJPM Apr 2 '17 at 0:07
  • \$\begingroup\$ Are preceding newlines allowed? \$\endgroup\$ – fergusq Apr 2 '17 at 9:13
  • \$\begingroup\$ @fergusq as they would (drastically) alter the output figure in a visible way, no. \$\endgroup\$ – SEJPM Apr 2 '17 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.

| improve this answer | | | | |
\$\endgroup\$
4
\$\begingroup\$

Octave, 45 44 bytes

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

Try it online!

| improve this answer | | | | |
\$\endgroup\$
  • \$\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 '17 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.

| improve this answer | | | | |
\$\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,#}]&
| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ Amusing remark: you don't need the comma after X :) \$\endgroup\$ – Greg Martin Apr 1 '17 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\$ – Martin Ender Apr 1 '17 at 19:34
  • 2
    \$\begingroup\$ Still overthinking it... #^2+#2^2 is shortest. \$\endgroup\$ – Martin Ender Apr 1 '17 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\$ – ngenisis Apr 3 '17 at 19:00
  • \$\begingroup\$ @MartinEnder I initially tried Array but didn't think to set the argument to a variable. \$\endgroup\$ – ngenisis Apr 3 '17 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.
| improve this answer | | | | |
\$\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.

| improve this answer | | | | |
\$\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
}
| improve this answer | | | | |
\$\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

| improve this answer | | | | |
\$\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.
| improve this answer | | | | |
\$\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!

| improve this answer | | | | |
\$\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
| improve this answer | | | | |
\$\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)
| improve this answer | | | | |
\$\endgroup\$
  • 1
    \$\begingroup\$ p(end=' 'if(i*i+j*j)%n-1else'X') for 95 bytes \$\endgroup\$ – ovs Apr 2 '17 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.

| improve this answer | | | | |
\$\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!

| improve this answer | | | | |
\$\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
| improve this answer | | | | |
\$\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
| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ You can replace the last map with a <$>, right? \$\endgroup\$ – k_g Apr 1 '17 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\$ – Ørjan Johansen Apr 2 '17 at 0:07
  • \$\begingroup\$ @k_g yes thank you \$\endgroup\$ – Generic Display Name Apr 2 '17 at 0:43
  • \$\begingroup\$ @ØrjanJohansen duly noted :) \$\endgroup\$ – Generic Display Name Apr 2 '17 at 0:44
0
\$\begingroup\$

J, 20 bytes

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

Try it online!

| improve this answer | | | | |
\$\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...

| improve this answer | | | | |
\$\endgroup\$

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.