24
\$\begingroup\$

The task

In this challenge, your task is to write a program in a programming language L that takes a positive integer n, and outputs the sum of the proper divisors of n (sequence A001065 on OEIS). It should return the correct output for any 1 ≤ n ≤ 10 000. Here are the first 10 outputs:

0, 1, 1, 3, 1, 6, 1, 7, 4, 8

Furthermore, your program must be a fake polyglot, which means the following. It is a valid program in another programming language L', and for each input 1 ≤ n ≤ 10 (the test cases above), it returns the sum of proper divisors of n, but there exists some 11 ≤ n ≤ 10 000 for which it doesn't return the correct result. It may return something incorrect, loop forever, crash etc. It can give a wrong result for all n ≥ 11, for some of them or just one.

Rules and scoring

You can write a full program or a function, and you can have different means of input and output in the two languages. The lowest byte count wins. Standard rules apply. In this challenge, different major versions or implementations of a language are considered distinct.

Note that if you use programming languages with non-ASCII encodings (as many do on this site), the same sequence of bytes must be used for both languages. This means that you must either convert between potentially different code pages or suffer penalties for multi-byte Unicode characters.

Additional test cases

20 -> 22
36 -> 55
180 -> 366
997 -> 1
2875 -> 869
10000 -> 14211
\$\endgroup\$

7 Answers 7

10
\$\begingroup\$

JavaScript (ES6), V8 / SpiderMonkey vs Chakra, 66 63 bytes

n=>[...Array(n)].map((_,d)=>s+=n%d?0:d,[0,n>10].sort(x=>s=x))|s

Demo

let f =

n=>[...Array(n)].map((_,d)=>s+=n%d?0:d,[0,n>10].sort(x=>s=x))|s

console.log(JSON.stringify(
  [...Array(20)].map((_, n) => n + 1).map(f)
))

Output

Output of the above snippet on Chrome and Firefox (all correct):

[0,1,1,3,1,6,1,7,4,8,1,16,1,10,9,15,1,21,1,22]

Output on Edge (off by 1, starting at n = 11):

[0,1,1,3,1,6,1,7,4,8,2,17,2,11,10,16,2,22,2,23]

Why?

No algorithm is imposed by the specification for the .sort() method. It's not even required to be stable. Therefore, each JavaScript engine uses its very own implementation.

However, [0,1].sort(x=>x) gives [0,1] with all engines.

So what's the difference?

What's happening here is that Chakra is passing 1 as the first parameter of the first (and only) iteration to the callback function (asking for a comparison of 1 with 0), while V8 and SpiderMonkey are passing 0 (asking for a comparison of 0 with 1).

You can use the following snippet to check what your browser is doing.

[0, 1].sort((x, y) => console.log("Let's compare " + x + " with " + y + "!"))

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This is an acceptable solution. I'll clarify it in the main post. \$\endgroup\$
    – Zgarb
    Aug 1, 2017 at 15:01
8
\$\begingroup\$

05AB1E / Jelly,  9  8 bytes

The byte-code (hexadecimal):

d1 a8 4f 71 0d ad 53 fa

Using Jelly's code-page returns incorrect results for any excessive number (e.g. an input of 12 returns 12 rather than 16):

ẎƭOqÆḌS«

Try it online!

Using 05AB1E's code-page returns correct results:

ѨOqмλSú

Try it online!

How?

05AB1E parses up to and including the 71 (q) which instructs to quit and then stops parsing:

ѨOq - Takes input from stdin
Ñ    - get divisors
 ¨   - remove right-most (the input value itself - yielding proper divisors)
  O  - sum
   q - quit (causing an implicit print of the top of the stack)
...мλSú is never parsed

Jelly parses the whole program up-front as three links due to the effect of the bytes without an assigned meaning, ƭ and q acting as delimiters. The entry point of a program is it's final link:

Ẏ - Link 1 (never used), tighten list
...ƭ delimits links 1 & 2)

O - Link 2 (never used), cast from characters to their ordinals
...q delimits link 2 and the main link

ÆḌS« - Main link: number, n
ÆḌ   - proper divisors
  S  - sum
   « - minimum of that and n
     - as a full-program: implicit print
\$\endgroup\$
5
  • \$\begingroup\$ That's 05AB1E / Jelly? \$\endgroup\$ Aug 1, 2017 at 14:32
  • \$\begingroup\$ Yeah, fixed, thanks; I was just writing up the explanation. \$\endgroup\$ Aug 1, 2017 at 14:45
  • \$\begingroup\$ ÆḌSD saves a byte. \$\endgroup\$
    – Dennis
    Aug 1, 2017 at 15:08
  • \$\begingroup\$ @Dennis Or better ÆḌSṚ. \$\endgroup\$ Aug 1, 2017 at 15:09
  • \$\begingroup\$ @Dennis - thanks, thought of a different way while eating :) \$\endgroup\$ Aug 1, 2017 at 15:51
8
\$\begingroup\$

Python 2 and Python 3, 58 bytes

TIO for Python 2

TIO for Python 3

lambda n:sum(i*(n<11or''==b'')for i in range(1,n)if n%i<1)

It works in python 2, but for every n > 10 it would output 0 in python 3.
All because of different approaches in comparing strings with bytes:

  • in Python 2 '' == b''
  • in Python 3 '' != b''
\$\endgroup\$
7
\$\begingroup\$

JavaScript (Node.js) and PHP, 73 70 bytes

function($n){for($d=$i=0;++$i<$n;)$d+=$i*!($n%$i);return"$n">10?0:$d;}

In both languages, this is an anonymous function. JavaScript gives the correct result, but PHP gives 0 for all n >= 11.

Try it JS!

Try it PHP!

How it works

Both languages do the same thing at first: iterate from 1 up to n-1, keeping a running sum of all numbers i for which n % i = 0.

What causes the difference in behaviour is the final part:

return"$n">10?0:$d;

In JavaScript, "$n" is just a string literal. The comparison > with 10 casts it to a number implicitly, but since it doesn't look like a number, it becomes NaN. NaN gives false when compared with a number in any way. As a result, $d is always returned.

However, in PHP, "$n" is a string containing the value of $n. When PHP casts this to a number, it simply becomes the value of $n. If it's greater than 10, then 0 is returned instead of $d.

\$\endgroup\$
6
\$\begingroup\$

Python 3 / Python 2, 64 60 58 bytes

Thanks to @officialaimm for 2 bytes off

lambda n:sum(d*(round((n>10)*.5)==n%d)for d in range(1,n))

In Python 3 this gives the correct results. In Python 2 the ouput is wrong for inputs exceeding 10. The code exploits banker's rounding, which is done by Python 3 but not by Python 2.

Try it online! Python 3 (correct), Python 2 (wrong for n > 10).

\$\endgroup\$
1
  • \$\begingroup\$ You won't need [ ]. \$\endgroup\$ Aug 1, 2017 at 16:05
6
\$\begingroup\$

Python 3 / Python 2, 47 bytes

lambda n:sum(d*(n%d<1)for d in range(10/n>0,n))

An unnamed function, fake in Python 2.

Try it online for Python 3 or Python 2

In Python 2 / is integer division with integer arguments, whereas in Python 3 it is division.

When n exceeds 10 10/n evaluates to 0 in Python 2, but to a small positive number in Python 3 (this is certainly true up to the maximum required of 10,000 at least).

As such 10/n>0 evaluates to True for Python 3 and range(10/n>0,n) is equivalent to range(1,n) while in Python 2 10/n>0 evaluates to False when n exceeds 10 whereupon range(10/n>0,n) becomes equivalent to range(0,n) causing n%d to attempt to perform modulo zero arithmetic, raising a ZeroDivisionError.

\$\endgroup\$
5
\$\begingroup\$

Jelly / 05AB1E, 12 bytes

What Jelly sees:

11⁻iẎƭO}qÆḌS

Try it online!

Explanation:

q is unsupported in Jelly, so Jelly only "sees" what's after the q.

ÆḌS
ÆḌ  Proper divisors
  S Sum

What 05AB1E sees:

11‹iѨO}qмλS

Try it online!

Explanation:

11‹iѨO}qмλS Implicit input multiple times
11           Push 11
  ‹          Less than 11?
   i   }     If equals 1, then
    Ñ         Divisors
     ¨        Remove last
      O       Sum
       q     Implicit print and quit
        м    Negative filter
         λ   Undefined, ignored error
          S  Split into chars

Of course everything after "quit" doesn't actually happen.

\$\endgroup\$
3
  • \$\begingroup\$ I wish ÆḌS would have been valid on its own... Extraordinary answer! \$\endgroup\$
    – Mr. Xcoder
    Aug 1, 2017 at 14:02
  • \$\begingroup\$ @Mr.Xcoder I'm not sure how мλS would work in 05AB1E. \$\endgroup\$ Aug 1, 2017 at 14:04
  • \$\begingroup\$ Emphasize on I wish :P \$\endgroup\$
    – Mr. Xcoder
    Aug 1, 2017 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.