Fake divisor sum polyglots

23

1

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

Zgarb

Posted 2017-08-01T13:34:02.107

Reputation: 39 083

Answers

10

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 + "!"))

Arnauld

Posted 2017-08-01T13:34:02.107

Reputation: 111 334

1This is an acceptable solution. I'll clarify it in the main post. – Zgarb – 2017-08-01T15:01:17.140

8

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

Dead Possum

Posted 2017-08-01T13:34:02.107

Reputation: 3 256

7

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

Jonathan Allan

Posted 2017-08-01T13:34:02.107

Reputation: 67 804

That's 05AB1E / Jelly? – Erik the Outgolfer – 2017-08-01T14:32:39.890

Yeah, fixed, thanks; I was just writing up the explanation. – Jonathan Allan – 2017-08-01T14:45:52.030

ÆḌSD saves a byte. – Dennis – 2017-08-01T15:08:02.240

@Dennis Or better ÆḌSṚ. – Erik the Outgolfer – 2017-08-01T15:09:13.777

@Dennis - thanks, thought of a different way while eating :) – Jonathan Allan – 2017-08-01T15:51:00.963

7

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.

Business Cat

Posted 2017-08-01T13:34:02.107

Reputation: 8 927

6

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).

Luis Mendo

Posted 2017-08-01T13:34:02.107

Reputation: 87 464

You won't need [ ]. – officialaimm – 2017-08-01T16:05:31.787

6

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.

Jonathan Allan

Posted 2017-08-01T13:34:02.107

Reputation: 67 804

5

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.

Erik the Outgolfer

Posted 2017-08-01T13:34:02.107

Reputation: 38 134

I wish ÆḌS would have been valid on its own... Extraordinary answer! – Mr. Xcoder – 2017-08-01T14:02:31.923

@Mr.Xcoder I'm not sure how мλS would work in 05AB1E. – Erik the Outgolfer – 2017-08-01T14:04:52.797

Emphasize on I wish :P – Mr. Xcoder – 2017-08-01T14:05:20.340