Write a function that tells you which of its lines has been removed

28

8

Write a function that contains five lines.

If you run the function as-is, it should return 0.

If you remove any one of the five lines and run the function, it should tell you which of the lines has been removed (e.g., if you remove the final line it should return 5).

Brevity, novelty, and elegance all deserve consideration. Highest upvoted solution (after a reasonable amount of time) wins.

jawns317

Posted 2013-12-28T03:34:56.803

Reputation: 1 132

4Can the function take a parameter? – jeremy – 2013-12-28T04:54:41.987

6Does the function declaration count as one of the lines if we want to use that sort of language, or is only the body counted? – meiamsome – 2013-12-28T04:58:10.653

1Also, do our lines need to be numbered 1, 2, 3, 4, 5 or is any numbering scheme allowed? – meiamsome – 2013-12-28T05:11:38.993

@Jeremy, yes, that's fine. – jawns317 – 2013-12-28T12:20:22.483

@meiamsome, only the body counts, and the lines should be numbered 1, 2, 3, 4, 5 for the purpose of return values. – jawns317 – 2013-12-28T12:22:36.620

can each "line" of the function contain more than one statement? Can the function leak in the global scope? ... I made the JavaScript answer assuming yes and yes :) – xem – 2013-12-28T18:36:44.647

Answers

18

Ruby

Eschewing magic numbers since it's not code golf.

def f
  r=2^3^4^5
  defined?(r) ? r^=2 : r=1^3^4^5
  r^=3
  r^=4
  r^=5
end

Each line strips its own number out of 1^2^3^4^5. It's Ruby, so the last line defines the return value.

histocrat

Posted 2013-12-28T03:34:56.803

Reputation: 20 600

13

JavaScript ( 134   77   69   65   60 chars)

→ live demo ←

function(n){
a=n-=1
n-=2
+3
+4;if(this.a)return 5
return n;var a
}

call this function with n = 10.

  • If no line is missing, line 5 returns n == 0.
  • If line 1 is missing, line 5 returns n == 1.
  • If line 2 is missing, line 5 returns n == 2.
  • If line 3 is missing, line 5 returns n == 3.
  • If line 4 is missing, line 5 returns n == 4.
  • If line 5 is missing, the var "a" becomes global and line 4 detects that to return "5".
  • If line 5 is present, the JS engine performs "variable hoisting", "a" becomes a local var, and line 4 doesn't return "5".



Previous versions:

65 chars

function(n){
a=n-=1
n-=2
+3
+4;if(this.a)return 5
n-=5;return n;var a
}

(must be called with n = 15)

69 chars

function(n){
n-=1
n-=2
n-=3
a=n-=4;if(this.a)return 5
n-=5;return n;var a
}

(must be called with n = 15)

77 chars

function(){
a=
b=
c=
d=1;if(this.a)return 5
1;var a,b,c,d;return d?c?b?a?0:1:2:3:4
}

134 chars

function w(){
a=1;e=1;if(this.e)return 5
b=1;if(!a)return 1
c=1;if(!b)return 2
d=1;if(!c)return 3
var a,b,c,d,e;return d?0:4
}

non-golfed

  function whichlineisremoved(){
    /* 1 */ var a = 1; e = 1; if(window.e) return 5;
    /* 2 */ var b = 1, a; if(!a) return 1;
    /* 3 */ var c = 1, b; if(!b) return 2;
    /* 4 */ var d = 1, c; if(!c) return 3;
    /* 5 */ var e = 1, d; if(!d) return 4; return 0;
  }

xem

Posted 2013-12-28T03:34:56.803

Reputation: 5 523

What exactly does the var a after the return do? In theory, it shouldn't be reached. – Braden Best – 2014-02-13T03:24:56.717

@B1KMusic, in fact it is "reached" due to something called JavaScript variable hoisting. When JS is "compiled", all the "var" declarations are virtually placed at the beginning of the functions in which they are. – xem – 2014-02-13T08:19:39.793

Hmm, that's odd. Is there a practical use for this in the language, or is this purely a golf/exploit? I don't recall reading anything about variable hoisting in Mozilla's documentation. – Braden Best – 2014-02-13T21:32:02.557

it's a JS feature. Described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting

– xem – 2014-02-14T03:19:13.350

Ah, so it's more of an exploit for golfing. – Braden Best – 2014-02-14T03:29:41.313

6

Python

If parameters are allowed, then this will work:

def f(n=10):
    n -= 1
    n -= 2
    n -= 3
    if n == 4: return 0 if f(7) else 5
    return n - 4 or 4

Volatility

Posted 2013-12-28T03:34:56.803

Reputation: 3 206

4

R

f <- function() {
  T <- FALSE
  F <- TRUE
  month.abb <- TRUE
  (pi <- 5)
  T + (!F) * 2 + (!isTRUE(month.abb)) * 3 + (pi != 5) * 4
}

The function uses built-in "constants" and assigns another value to each of them. If all of these variables are equal to the new value, the function returns 0. Logical values are transformed to numeric ones because of the mathematical operators. The parentheses around the 4th line allow visibly returning its result (if it's the last command).

Sven Hohenstein

Posted 2013-12-28T03:34:56.803

Reputation: 2 464

3

Lua 5.2+

55 chars in the function body excluding newlines. I couldn't come up with anything better but this:

function f()
return 7--[[
return 1--[=[]]-2
--[[
-2--[=[]]
-5--]=]--]]-1
end

Hoping to get extra points for comments abuse :P

The reason it does not work in 5.1 is that nested [[]] were removed, and in 5.1 it gives a compilation error instead of ignoring it like 5.2 does.

  • If none of the lines are removed, the function body is eqivalent to return 7-2-5
  • If the first line is removed, return 1
  • If the second, return 7-5
  • If the third, return 7-2-2
  • If the fourth, return 7-2-1
  • If the fifth, return 7-2

mniip

Posted 2013-12-28T03:34:56.803

Reputation: 9 396

2

Ruby

I tried doing it with bitwise operations and then I realized there is a much simpler solution using lists! This challenge is best served by a programming language that automatically returns the last value it sees, such as Ruby.

def tellMe(x=[1,2,3,4,5])
    x.delete(1)
    x.delete(2)
    x.delete(3)
    x.delete(4);x[0]
    x.delete(5);x==[]?0:x[0]
end

danmcardle

Posted 2013-12-28T03:34:56.803

Reputation: 695

2

Befunge doesn't have explicit functions, but here is what I'd call a function in Befunge:

v^    <
>v
1>v
 2>v
##3>5v
$0v4 >
>>>>>>^

The first and last lines are function start and function end. It does the closest thing to "return", that is, it pushes the correct value onto the stack.

Justin

Posted 2013-12-28T03:34:56.803

Reputation: 19 757

1

New Answer

I found another solution. That's so bad, I liked the math one so much. This solution uses recursion and global variables (yuck!) to tell if every line has been run or not. I wanted to do something different from the other solutions, so this isn't much elegant, but it works properly :)

PHP

function LOL($a) {
    if (!$a) { LOL(true); if (!$GLOBALS['b']) return 2; if (!$GLOBALS['c']) return 3; if (!$GLOBALS['d']) return 4; if (!$GLOBALS['e']) return 5; return 0; } 
    if ($a) $GLOBALS['b'] = true; else return 1;
    $GLOBALS['c'] = true;
    $GLOBALS['d'] = true;
    $GLOBALS['e'] = true;
}

I really enjoyed this challenge, thank you! :)


Old Answer

I solved it using maths. If each variable is seen as an unknown, and we do one declaration per line, there are five unknowns and five lines of code: this leads us to the following 5x5 system:

b+c+d+e = 1;
a+c+d+e = 2;
a+b+d+e = 3;
a+b+c+e = 4;
a+b+c+d = 5;
//Solutions are displayed in the code below.

Once I found the values, I hardcoded them and added some basic stuff.

PHP

function LOL(){
    $a = 2.75;
    $b = 1.75;
    $c = 0.75;
    $d = -0.25; if ($a+$b+$c+$d == 5) return $a+$b+$c+$d;
    $e = -1.25; return $a+$b+$c+$d+$e;
}

Note: The Old Answer won't work if left as-is.

Vereos

Posted 2013-12-28T03:34:56.803

Reputation: 4 079

I like the system of linear equations idea. – M L – 2015-12-28T19:41:15.537

1

beeswax, 86 bytes

Trying out my first invented esolang. After initial confusion I found that the solution is so simple.

_1 p
_^v>~2+p
   >   >~3+p
       >   >~4+X@7~8+~@$^^{;
           >    >~5+@7~8+~@${;

Explanation:

beeswax programs work on a 2D hexagonal grid. Programs are stored in a rectangular format.

    a — b — c — d
   / \ / \ / \ /
  e — f — g — h
 / \ / \ / \ /
i — j — k — l

is stored as

abcd
efgh
ijkl

The instructions for moving in certain directions are:

    b — d 
   / \ / \                                  bd
  < —IP — >    or in compact form (β=IP):   <β>
   \ / \ /                                   pq
    p — q

Short explanation

_1 p Create an IP, add 1, then redirect IP to line 2

_^v>~2+p Create another IP, just in case line 1 is missing, slow down IP to make sure IP from line one is ahead, then add 2, then redirect to line 3

> >~3+p Add 3, then redirect to line 4

> >~4+X@7~8+~@$^^{; Add 4, then set 2nd lstack value to 15, then XOR lstack top and 2nd values, slow down IP (to make sure IP in line 5 is ahead, if line 5 exists) and output the result, then terminate the program.

> >~5+@7~8+~@${; Add 5, then do the same as in line 4, except the slow down.

Basically the program just calculates a sum xor 15

  • Program intact: (1+2+3+4+5) xor 15 = 0
  • Line 1 missing: (2+3+4+5) xor 15 = 1
  • Line 2 missing: (1+3+4+5) xor 15 = 2
  • Line 3 missing: (1+2+4+5) xor 15 = 3
  • Line 4 missing: (1+2+3+5) xor 15 = 4
  • Line 5 missing: (1+2+3+4) xor 15 = 5

The additional > in lines 3 to 5 just guarantee that if one of lines 2 to 4 are missing, the IP still gets redirected properly and doesn’t leave the program.

You can clone my beeswax interpreter, written in Julia, from my GitHub repository

The readme on GitHub is more up to date and better structured than the esolangs page.

M L

Posted 2013-12-28T03:34:56.803

Reputation: 2 865

0

Bash, 131 chars

#!/bin/bash

# the function:
function f(){
  a=1;
  b=2;
  c=3;
  d=4;[ ! $1 ]&&f 1&&return 5||true
  [ $1 ]&&return 6;e=5;s=$((a+b+c+d+e));return $((15-$s))
}

# call it:
f
# report the result:
echo Removed line $?

It's all straightforward up to line 5. Then it needs to detect if the final line is gone. This takes advantage of permitted function parameters by calling itself recursively, once, to test its own success value when it's being told to fail on line 5, and if line 5 is removed, line 4 returns 5 instead.

(Note: it's down to a minimum of 131 characters if stripping out everything but the function, ditching whitespace, and changing /bin/bash to /bin/sh)

Riot

Posted 2013-12-28T03:34:56.803

Reputation: 4 639

0

MuPAD, 57 chars

subs(()->
-d(1)
-d(2)
-d(3)
-d(4)
-d(5)
,d=Dom::IntegerMod(15))

Christopher Creutzig

Posted 2013-12-28T03:34:56.803

Reputation: 383

0

Common LISP:

(defun which-line-is-removed (&aux (x 30)) 
  (decf x 2)
  (decf x 4)
  (decf x 8)
  (decf x 16) 5
  (if (zerop x) 0 (log x 2))
)

NB: Having ending parenthesis on it's own line is considered bad style, but since other languages has end and } I assume it is allowed.

Sylwester

Posted 2013-12-28T03:34:56.803

Reputation: 3 678

0

Javascript

function(){
/*aa*/if(arguments.callee.toString().indexOf("*"+"a".repeat(6)+"*")==-1)return 5;
/*aaa*/if(arguments.callee.toString().indexOf("*"+"a".repeat(5)+"*")==-1)return 4;
/*aaaa*/if(arguments.callee.toString().indexOf("*"+"a".repeat(3)+"*")==-1)return 2;
/*aaaaa*/if(arguments.callee.toString().indexOf("*"+"a".repeat(4)+"*")==-1)return 3;
/*aaaaaa*/return +!~arguments.callee.toString().indexOf("*"+"a".repeat(2)+"*");
};

SuperJedi224

Posted 2013-12-28T03:34:56.803

Reputation: 11 342