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 code-golf 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.
-
\$\begingroup\$ Looks much better if you use the domain [0,n] in my opinion. Here is an example with input 42. \$\endgroup\$R. Kap– R. Kap2017年04月01日 19:11:22 +00:00Commented 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\$Ørjan Johansen– Ørjan Johansen2017年04月02日 00:02:02 +00:00Commented Apr 2, 2017 at 0:02
-
\$\begingroup\$ @ØrjanJohansen indeed the former. \$\endgroup\$SEJPM– SEJPM2017年04月02日 00:07:58 +00:00Commented Apr 2, 2017 at 0:07
-
\$\begingroup\$ Are preceding newlines allowed? \$\endgroup\$fergusq– fergusq2017年04月02日 09:13:24 +00:00Commented Apr 2, 2017 at 9:13
-
\$\begingroup\$ @fergusq as they would (drastically) alter the output figure in a visible way, no. \$\endgroup\$SEJPM– SEJPM2017年04月02日 09:23:56 +00:00Commented Apr 2, 2017 at 9:23
18 Answers 18
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.
-
\$\begingroup\$ This also works:
@(n)[(mod((x=(0:n-1).^2)+x',n)==1)*88,'']. In certain systems Octave treats character0as a space \$\endgroup\$Luis Mendo– Luis Mendo2017年04月02日 02:35:39 +00:00Commented Apr 2, 2017 at 2:35
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.
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,#}]&
-
\$\begingroup\$ Amusing remark: you don't need the comma after
X:) \$\endgroup\$Greg Martin– Greg Martin2017年04月01日 19:31:17 +00:00Commented Apr 1, 2017 at 19:31 -
1\$\begingroup\$ I think you're better off with
ArrayandNorm:Grid@Array[If[Mod[Norm@{##}^2,x]==1,X]&,{x=#,#},0]&\$\endgroup\$Martin Ender– Martin Ender2017年04月01日 19:34:52 +00:00Commented Apr 1, 2017 at 19:34 -
2\$\begingroup\$ Still overthinking it...
#^2+#2^2is shortest. \$\endgroup\$Martin Ender– Martin Ender2017年04月01日 19:45:27 +00:00Commented Apr 1, 2017 at 19:45 -
\$\begingroup\$ @GregMartin So if the first argument to
Ifis neitherTrueorFalse, you need the fourth argument or it remains unevaluated, butIf[False,_]returnsNull. Weird. \$\endgroup\$user61980– user619802017年04月03日 19:00:29 +00:00Commented Apr 3, 2017 at 19:00 -
\$\begingroup\$ @MartinEnder I initially tried
Arraybut didn't think to set the argument to a variable. \$\endgroup\$user61980– user619802017年04月03日 19:01:19 +00:00Commented Apr 3, 2017 at 19:01
CJam, 23 bytes
ri:X,2f#_ff{+X%(S'X?}N*
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.
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.
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[" "]}_;["
"]}_}
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
}
Jelly, (削除) 14 (削除ここまで) 13 bytes
R2+þ`%=1ị)X Y
The x-axis is inverted.
How it works
R2+þ`%=1ị)X Y Main link. Argument: n
R Range; yield [1, ..., n].
2 Square; yield [12, ..., n2].
+þ` Self table addition; compute x+y for all x and y in [12, ..., n2],
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.
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()
- saved 4 bytes: omitted variable c in c=' 'if(ii+jj)%n-1else'X'
- saved 3 bytes: Thanks to ovs (modified print statement)
-
1
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.
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.
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
MATL, 13 bytes
:qU&+G1円=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
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.
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
-
\$\begingroup\$ You can replace the last
mapwith a<$>, right? \$\endgroup\$k_g– k_g2017年04月01日 23:20:28 +00:00Commented 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\$Ørjan Johansen– Ørjan Johansen2017年04月02日 00:07:01 +00:00Commented Apr 2, 2017 at 0:07
-
\$\begingroup\$ @ØrjanJohansen duly noted :) \$\endgroup\$Generic Display Name– Generic Display Name2017年04月02日 00:44:39 +00:00Commented Apr 2, 2017 at 0:44
Explore related questions
See similar questions with these tags.