?::`}:("(!@
perfect:
{:{:;%"}
+puts; "
}zero: "
}else{(:
"negI" _~
""""""{{{"!@
The Latin characters perfect puts zero else neg I
are actually just comments*.
i.e. if the input is perfect a 0
is printed, otherwise -1
is.
Try it online!
* so this or this work too...
?::`}:("(!@ ?::`}:("(!@
: BEWARE :
{:{:;%"} {:{:;%"}
+ ; " +LAIR; "
} : " } OF : "
} {(: }MINO{(:
" " _~ "TAUR" _~
""""""{{{"!@ """"""{{{"!@
How?
Takes as an input a positive integer n
and places an accumulator variable of -n
onto the auxiliary stack, then performs a divisibility test for each integer from n-1
down to, and including, 1
, adding any which do divide n
to the accumulator. Once this is complete if the accumulator variable is non-zero a -1
is output, otherwise a 0
is.
The ?::`}:(
is only executed once, at the beginning of execution:
?::`}:( Main,Aux
? - take an integer from STDIN and place it onto Main [[n],[]]
: - duplicate top of Main [[n,n],[]]
: - duplicate top of Main [[n,n,n],[]]
` - negate top of Main [[n,n,-n],[]]
} - place top of Main onto Aux [[n,n],[-n]]
: - duplicate top of Main [[n,n,n],[-n]]
( - decrement top of Main [[n,n,n-1],[-n]]
The next instruction, "
, is a no-op, but we have three neighbouring instructions so we branch according to the value at the top of Main, zero takes us forward, while non-zero takes us right.
If the input was 1
we go forward because the top of Main is zero:
(!@ Main,Aux
( - decrement top of Main [[1,1,-1],[-1]]
! - print top of Main, a -1
@ - exit the labyrinth
But if the input was greater than 1
we turn right because the top of Main is non-zero:
:} Main,Aux
: - duplicate top of Main [[n,n,n-1,n-1],[-n]]
} - place top of Main onto Aux [[n,n,n-1],[-n,n-1]]
At this point we have a three-neighbour branch, but we know n-1
is non-zero, so we turn right...
"% Main,Aux
" - no-op [[n,n,n-1],[-n,n-1]]
% - place modulo result onto Main [[n,n%(n-1)],[-n,n-1]]
- ...i.e we've got our first divisibility indicator n%(n-1), an
- accumulator, a=-n, and our potential divisor p=n-1:
- [[n,n%(n-1)],[a,p]]
We are now at another three-neighbour branch at %
.
If the result of %
was non-zero we go left to decrement our potential divisor, p=p-1
, and leave the accumulator, a
, as it is:
;:{(:""}" Main,Aux
; - drop top of Main [[n],[a,p]]
: - duplicate top of Main [[n,n],[a,p]]
{ - place top of Aux onto Main [[n,n,p],[a]]
- three-neighbour branch but n-1 is non-zero so we turn left
( - decrement top of Main [[n,n,p-1],[a]]
: - duplicate top of Main [[n,n,p-1,p-1],[a]]
"" - no-ops [[n,n,p-1,p-1],[a]]
} - place top of Main onto Aux [[n,n,p-1],[a,p-1]]
" - no-op [[n,n,p-1],[a,p-1]]
% - place modulo result onto Main [[n,n%(p-1)],[a,p-1]]
- ...and we branch again according to the divisibility
- of n by our new potential divisor, p-1
...but if the result of %
was zero (for the first pass only when n=2
) we go straight on to BOTH add the divisor to our accumulator, a=a+p
, AND decrement our potential divisor, p=p-1
:
;:{:{+}}""""""""{(:""} Main,Aux
; - drop top of Main [[n],[a,p]]
: - duplicate top of Main [[n,n],[a,p]]
{ - place top of Aux onto Main [[n,n,p],[a]]
: - duplicate top of Main [[n,n,p,p],[a]]
{ - place top of Aux onto Main [[n,n,p,p,a],[]]
+ - perform addition [[n,n,p,a+p],[]]
} - place top of Main onto Aux [[n,n,p],[a+p]]
} - place top of Main onto Aux [[n,n],[a+p,p]]
""""""" - no-ops [[n,n],[a+p,p]]
- a branch, but n is non-zero so we turn left
" - no-op [[n,n],[a+p,p]]
{ - place top of Aux onto Main [[n,n,p],[a+p]]
- we branch, but p is non-zero so we turn right
( - decrement top of Main [[n,n,p-1],[a+p]]
: - duplicate top of Main [[n,n,p-1,p-1],[a+p]]
"" - no-ops [[n,n,p-1,p-1],[a+p]]
} - place top of Main onto Aux [[n,n,p-1],[a+p,p-1]]
At this point if p-1
is still non-zero we turn left:
"% Main,Aux
" - no-op [[n,n,p-1],[a+p,p-1]]
% - modulo [[n,n%(p-1)],[a+p,p-1]]
- ...and we branch again according to the divisibility
- of n by our new potential divisor, p-1
...but if p-1
hit zero we go straight up to the :
on the second line of the labyrinth (you've seen all the instructions before, so I'm leaving their descriptions out and just giving their effect):
:":}"":({):""}"%;:{:{+}}"""""""{{{ Main,Aux
: - [[n,n,0,0],[a,0]]
" - [[n,n,0,0],[a,0]]
- top of Main is zero so we go straight
- ...but we hit the wall and so turn around
: - [[n,n,0,0,0],[a,0]]
} - [[n,n,0,0],[a,0,0]]
- top of Main is zero so we go straight
"" - [[n,n,0,0],[a,0,0]]
: - [[n,n,0,0,0],[a,0,0]]
( - [[n,n,0,0,-1],[a,0,0]]
{ - [[n,n,0,0,-1,0],[a,0]]
- top of Main is zero so we go straight
- ...but we hit the wall and so turn around
( - [[n,n,0,0,-1,-1],[a,0]]
: - [[n,n,0,0,-1,-1,-1],[a,0]]
"" - [[n,n,0,0,-1,-1,-1],[a,0]]
} - [[n,n,0,0,-1,-1],[a,0,-1]]
- top of Main is non-zero so we turn left
" - [[n,n,0,0,-1,-1],[a,0,-1]]
% - (-1)%(-1)=0 [[n,n,0,0,0],[a,0,-1]]
; - [[n,n,0,0],[a,0,-1]]
: - [[n,n,0,0,0],[a,0,-1]]
{ - [[n,n,0,0,0,-1],[a,0]]
: - [[n,n,0,0,0,-1,-1],[a,0]]
{ - [[n,n,0,0,0,-1,-1,0],[a]]
+ - [[n,n,0,0,0,-1,-1],[a]]
} - [[n,n,0,0,0,-1],[a,-1]]
} - [[n,n,0,0,0],[a,-1,-1]]
""""""" - [[n,n,0,0,0],[a,-1,-1]]
- top of Main is zero so we go straight
{ - [[n,n,0,0,0,-1],[a,-1]]
{ - [[n,n,0,0,0,-1,-1],[a]]
{ - [[n,n,0,0,0,-1,-1,a],[]]
Now this {
has three neighbouring instructions, so...
...if a
is zero, which it will be for perfect n
, then we go straight:
"!@ Main,Aux
" - [[n,n,0,0,0,-1,-1,a],[]]
- top of Main is a, which is zero, so we go straight
! - print top of Main, which is a, which is a 0
@ - exit the labyrinth
...if a
is non-zero, which it will be for non-perfect n
, then we turn left:
_~"!@ Main,Aux
_ - place a zero onto Main [[n,n,0,0,0,-1,-1,a,0],[]]
~ - bitwise NOT top of Main (=-1-x) [[n,n,0,0,0,-1,-1,a,-1],[]]
" - [[n,n,0,0,0,-1,-1,a,-1],[]]
- top of Main is NEGATIVE so we turn left
! - print top of Main, which is -1
@ - exit the labyrinth
Wait, so truthy is for values that aren't perfect, and falsey is for values that are? – Esolanging Fruit – 2019-03-12T02:57:14.250
@EsolangingFruit Yes, though the actual output values don't really matter, so you can output true for perfect numbers if you wish – Jo King – 2019-03-12T02:58:53.190
Fair enough, but wording the challenge as "output whether it is not perfect" makes the test cases slightly confusing if you interpret "truthy" as meaning "values corresponding to true". – Esolanging Fruit – 2019-03-12T03:00:27.433
@EsolangingFruit Good point. I've renamed the test cases to
Imperfect
/Perfect
to make it clearer – Jo King – 2019-03-12T03:01:56.383Why is
1
not a perfect number?1 == 1
. – Tvde1 – 2019-03-12T07:36:16.4032@Tvde1 Proper divisors have to less than the number, otherwise no number other than
1
would be perfect, since every number is divisible by1
and itself. The sum of proper divisors of1
is0
– Jo King – 2019-03-12T07:40:21.070Are we allowed to assume there are no odd perfect numbers? – Grimmy – 2019-03-12T08:56:01.450
3
@Grimy Only if you can prove so. Good luck! (though I'm wondering how that would save bytes)
– Jo King – 2019-03-12T09:15:51.6901So no, too bad. It would cut the size of an ECMA regex answer by a factor of about 3. – Grimmy – 2019-03-12T09:18:10.540
3"Output can be two distinct and consistent values" - may we not use "truthy vs falsey" here (e.g. for Python using zero vs non zero; a list with content vs an empty list; and combinations thereof)? – Jonathan Allan – 2019-03-12T10:15:22.617