43
\$\begingroup\$

This challenge was inspired by a programming blog I frequent. Please see the original post here: A Programming Puzzle


Challenge

Define a function f:Q->Q such that f(f(n)) = -n for all non-zero integers n, and whereQ is the set of rational numbers.

Details

In whatever language you prefer, please define one function or program f that accepts as parameter one number n and returns or outputs one number f(n).

Input may be provided through whichever mechanism is most natural for your language: function argument, read from STDIN, command-line argument, stack position, voice input, gang signs, etc.

Output should be a return value from a function/program or printed to STDOUT.

I would like to restrict answers to functions that do not take advantage of program state or global memory/data that is visible from outside of the function f. For example, keeping a counter outside of f that counts how many times f was called and just doing a negation based on this count isn't very challenging or interesting for anyone. The decisions f makes should rely only on data within f's lexical scope.

However, this restriction is probably inappropriate for some stack-oriented languages or other types of languages that do not distinguish these types of data or scopes. Please use your best judgement to keep with the spirit of this challenge.


Scoring

Common code golf rules apply- your score is the number of bytes in your source code.

The minimal answer requires the domain and codomain of f to be a subset of the rationals Q. If you restrict your domain and codomain of f to the integers Z, then your score is the ceiling of 90% of the number of bytes in your source code.

Tiebreak

In the event of a tie, the following will be used in order:

  1. Fewest number of printable non-whitespace symbols in your source code
  2. Earliest date and time of answer submission

Edit

You are not required to support arbitrarily sized numbers. Please interpret the sets Z and Q as datatypes in your chosen language (typically integer and floating point, respectively).

If your solution relies entirely on the underlying structure or bit pattern of a data type, please describe its limitations and how it is being used.

\$\endgroup\$
  • 20
    \$\begingroup\$ f(n) = i*n -- pure math :P \$\endgroup\$ – Johannes Kuhn Jun 29 '13 at 17:33
  • 8
    \$\begingroup\$ @JohannesKuhn this is why the domain and codomain are restricted to the rationals \$\endgroup\$ – ardnew Jun 29 '13 at 17:36
  • \$\begingroup\$ Could you explain what f:Q->Q means? \$\endgroup\$ – beary605 Jun 29 '13 at 17:38
  • \$\begingroup\$ @beary605 it means f is a function mapping members of Q (rational numbers) to other members (possibly the same) of Q. see en.wikipedia.org/wiki/Function_(mathematics)#Notation \$\endgroup\$ – ardnew Jun 29 '13 at 17:41
  • 7
    \$\begingroup\$ I knew I'd seen this recently, but it took a while to remember where. A less tightly specified version on StackOverflow was recently closed. Over 100 answers. \$\endgroup\$ – Peter Taylor Jun 29 '13 at 19:36

32 Answers 32

1
2
0
\$\begingroup\$

Forth, 37 bytes

: f 9 @ if negate 0 else 1 then 9 ! ; 

Works at least in durexforth (it should at least, I couldn't type the whole line in because VICE was being stupid with my keybaord layout so I couldn't type the :). To run it in gforth you need to do variable 9 before, since it doesn't allow writing to arbitrary memory locations.

(Forth sadly doesn't work with floating point numbers.)

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

C, 80 bytes

#include <math.h>
double z(double x){return x==0.0?x:fabs(x)>0.5?0.5/x:-0.5/x;}

for to test

#include <stdio.h>      
#define P printf
#define R return
main()
{double i, j;
 for(i=-20;i<20;i+=1)
       P("z(z(%f))=%f\n", i, z(z(i)) );
 for(i=-2;i<-1;i+=0.1)
       P("z(z(%f))=%f\n", i, z(z(i)) );
 for(i= 2;i<3;i+=0.1)
       P("z(z(%f))=%f\n", i, z(z(i)) );
 P("z(z(%f))=%f\n", 0.1245447, z(z(0.1245447)) );
 R 0;
}

results where you can see that this is for every number in double except 0 and 2 other

/*
z(z(-20.000000))=20.000000
z(z(-19.000000))=19.000000
z(z(-18.000000))=18.000000
z(z(-17.000000))=17.000000
z(z(-16.000000))=16.000000
z(z(-15.000000))=15.000000
z(z(-14.000000))=14.000000
z(z(-13.000000))=13.000000
z(z(-12.000000))=12.000000
z(z(-11.000000))=11.000000
z(z(-10.000000))=10.000000
z(z(-9.000000))=9.000000
z(z(-8.000000))=8.000000
z(z(-7.000000))=7.000000
z(z(-6.000000))=6.000000
z(z(-5.000000))=5.000000
z(z(-4.000000))=4.000000
z(z(-3.000000))=3.000000
z(z(-2.000000))=2.000000
z(z(-1.000000))=1.000000
z(z(0.000000))=0.000000
z(z(1.000000))=-1.000000
z(z(2.000000))=-2.000000
z(z(3.000000))=-3.000000
z(z(4.000000))=-4.000000
z(z(5.000000))=-5.000000
z(z(6.000000))=-6.000000
z(z(7.000000))=-7.000000
z(z(8.000000))=-8.000000
z(z(9.000000))=-9.000000
z(z(10.000000))=-10.000000
z(z(11.000000))=-11.000000
z(z(12.000000))=-12.000000
z(z(13.000000))=-13.000000
z(z(14.000000))=-14.000000
z(z(15.000000))=-15.000000
z(z(16.000000))=-16.000000
z(z(17.000000))=-17.000000
z(z(18.000000))=-18.000000
z(z(19.000000))=-19.000000
z(z(-2.000000))=2.000000
z(z(-1.900000))=1.900000
z(z(-1.800000))=1.800000
z(z(-1.700000))=1.700000
z(z(-1.600000))=1.600000
z(z(-1.500000))=1.500000
z(z(-1.400000))=1.400000
z(z(-1.300000))=1.300000
z(z(-1.200000))=1.200000
z(z(-1.100000))=1.100000
z(z(2.000000))=-2.000000
z(z(2.100000))=-2.100000
z(z(2.200000))=-2.200000
z(z(2.300000))=-2.300000
z(z(2.400000))=-2.400000
z(z(2.500000))=-2.500000
z(z(2.600000))=-2.600000
z(z(2.700000))=-2.700000
z(z(2.800000))=-2.800000
z(z(2.900000))=-2.900000
z(z(0.124545))=-0.124545
*/
| improve this answer | |
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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