Definire una funzione f tale che f (f (n)) = -n per tutti gli interi diversi da zero n


43

Questa sfida è stata ispirata da un blog di programmazione che frequento. Si prega di consultare il post originale qui: Un puzzle di programmazione


Sfida

Definire una funzione f:Q->Qtale che f(f(n)) = -nper tutti gli interi diversi da zero ne dove si Qtrova l'insieme dei numeri razionali.

Dettagli

Nella lingua che preferisci, definisci una funzione o un programma fche accetta come parametro un numero ne restituisce o genera un numero f(n).

L'input può essere fornito attraverso qualsiasi meccanismo più naturale per la tua lingua: argomento della funzione, lettura da STDIN, argomento della riga di comando, posizione dello stack, input vocale, segni di gang, ecc.

L'output deve essere un valore di ritorno da una funzione / programma o stampato su STDOUT.

Vorrei limitare le risposte alle funzioni che non sfruttano lo stato del programma o la memoria / i dati globali visibili dall'esterno della funzione f. Ad esempio, tenere un contatore fuori da fquello conta quante volte è fstato chiamato e semplicemente fare una negazione basata su questo conteggio non è molto stimolante o interessante per nessuno. Le decisioni fda prendere dovrebbero basarsi solo sui dati nell'ambito di fapplicazione lessicale.

Tuttavia, questa limitazione è probabilmente inappropriata per alcune lingue orientate allo stack o altri tipi di lingue che non distinguono questi tipi di dati o ambiti. Ti preghiamo di usare il tuo miglior giudizio per mantenere lo spirito di questa sfida.


punteggio

Si applicano le regole comuni per il golf del codice: il tuo punteggio è il numero di byte nel codice sorgente.

La risposta minima richiede che il dominio e il codice di fessere un sottoinsieme dei razionali Q. Se limiti il ​​tuo dominio e il tuo codice fagli interi Z, il tuo punteggio è il limite del 90% del numero di byte nel tuo codice sorgente.

Tie-break

In caso di pareggio, nell'ordine verrà utilizzato quanto segue:

  1. Il minor numero di simboli stampabili non di spazi bianchi nel codice sorgente
  2. Prima data e ora di invio della risposta

modificare

Non è necessario supportare numeri di dimensioni arbitrarie. Si prega di interpretare gli insiemi Ze Qcome tipi di dati nella lingua prescelta (in genere rispettivamente numeri interi e virgola mobile).

Se la tua soluzione si basa interamente sulla struttura sottostante o sullo schema di bit di un tipo di dati, descrivi i suoi limiti e il modo in cui viene utilizzata.


20
f (n) = i * n - matematica pura: P
Johannes Kuhn,

8
@JohannesKuhn questo è il motivo per cui il dominio e il codice sono limitati ai razionali
ardnew,

Potresti spiegare cosa f:Q->Qsignifica?
beary605

@ beary605 significa che fè una funzione che associa i membri di Q(numeri razionali) ad altri membri (forse lo stesso) di Q. vedi en.wikipedia.org/wiki/Function_(mathematics)#Notation
ardnew

7
Sapevo di averlo visto di recente, ma ci è voluto un po 'di tempo per ricordare dove. Una versione meno rigorosamente specificata su StackOverflow è stata recentemente chiusa. Oltre 100 risposte.
Peter Taylor,

Risposte:


12

J, 9 punti (10 caratteri)

Basato sulla risposta di StackOverflow :

   (*-[*_1&^)

Prima idea (13 caratteri):

   ((-*)-2&|*+:)

   ((-*)-2&|*+:) _10 _9 _8 _7 _6 _5 _4 _3 _2 _1 0 1 2 3 4 5 6 7 8 9 10
_9 10 _7 8 _5 6 _3 4 _1 2 0 _2 1 _4 3 _6 5 _8 7 _10 9

   ((-*)-2&|*+:) _9 10 _7 8 _5 6 _3 4 _1 2 0 _2 1 _4 3 _6 5 _8 7 _10 9
10 9 8 7 6 5 4 3 2 1 0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _10

Funziona con input intero, ma produce output immaginario per valori in virgola mobile (la funzione deve produrre output razionale per input razionale secondo le specifiche)
Volatilità

5
@Volatilità, le specifiche sono formulate in modo confuso, ma mentre le leggo permette di limitare dominio e codomain a numeri interi.
Peter Taylor,

Hai bisogno delle parentesi?
Cyoce,

14

Python: 61 34 30 29 27 punti

f: Q -> Q

in matematica:

       | 0.5-x   if x is in Q \ Z
f(x) = |
       | x+0.5   if x is in Z

in Python:

f=lambda x:.5+[x,-x][x%1>0]

testato con

filter(lambda n: n[0] != -n[1], map(lambda n:(n,f(f(n))),range(0,50)))

logica dietro questo:

Quando prendi un numero intero ne lo inserisci, fotterrai x+0.5. Questo non è più un numero intero, quindi l'applicazione successiva sarà quella 0.5-(x+0.5)che è -x.

Crediti

Grazie a

  • Bakuriu per averlo ridotto da 61 a 34 caratteri.
  • Volatilità per ridurre ulteriormente la dimensione del codice a 30 caratteri.
  • copia per ridurre la dimensione del codice a 29 caratteri (e correggere un potenziale problema in virgola mobile).
  • aditsu per aver menzionato un'incoerenza derivante dalle modifiche sopra.

Gli appunti

Innanzitutto ho pensato che sarebbe andato tutto bene

f = lambda n: 1j*n

ma è f: N-> C e non è consentito: - /


1
Può essere ridotto a: f=lambda x:x%1>0and(-x+x%1)or x+.1che è lungo solo 34 caratteri.
Bakuriu,

f=lambda x:[x+.1,x%1-x](x%1>0)sono solo 30
Volatilità

1
Un char più breve: f=lambda x:[x+.5,.5-x][x%1>0]. Nota l'uso di .5 invece di .1 per aggirare i problemi di precisione
copia il

1
@AJMansfield 1.48 non è un numero intero.
Martin Thoma,

1
No, questo non significa che. Se lo menziona, avrebbe dovuto scrivere "tutti i numeri razionali". f:Q->Qsignifica solo che f associa il numero razionale ai numeri razionali. Che fa la mia definizione di f.
Martin Thoma,

11

C, 41 punti (41 o 45 caratteri)

Funziona con 32 e 64 bit.

f : Z -> Z(tranne INT_MAX):

f(n){return (abs(n)%2*2-1)*n+n?(-n<n)*2-1:0;}

Se non dobbiamo includere 0possiamo radere alcuni caratteri (41 caratteri):

f : Z -> Z(tranne 0& INT_MAX):

f(n){return (abs(n)%2*2-1)*n+(-n<n)*2-1;}

Questa funzione funziona dividendo tutti i numeri interi in 4 gruppi in base al loro segno e parità.

Quindi abbiamo le 4 diverse combinazioni:

+ even, + odd, - even, - odd

Dato che dobbiamo cambiare il segno del numero, ma non la parità dopo due passaggi, otteniamo due diverse sequenze possibili:

  + even -> - odd -> - even -> + odd -\
^-------------------------------------/

  + even -> + odd -> - even -> - odd -\
^-------------------------------------/

In questo esempio ho scelto il primo.

Per prima cosa dobbiamo mappare tutti i numeri interi positivi anche a numeri interi dispari negativi. Lo facciamo cambiando il segno e incrementando il numero (puoi anche scegliere di diminuire il numero):

f1(n) = -n + 1

Abbiamo quindi bisogno di mappare tutti gli interi negativi dispari a interi pari negativi. Dobbiamo assicurarci che f2(f1(n)) = -n:

f2(f1(n)) = -n
f2(-n + 1) = -n
f2(-n) = -n - 1
f2(n) = n - 1

Usando gli stessi metodi troviamo f3e f4:

f3(n) = -n - 1
f4(n) =  n + 1

Per combinare queste funzioni in una singola funzione, osserviamo che ogni volta nè anche cambiamo il segno ne ogni volta che nsiamo positivi incrementiamo di una e altrimenti diminuiamo di una:

f1(n) = -n + 1 (+ even)
f2(n) =  n - 1 (- odd)
f2(n) = -n - 1 (- even)
f4(n) =  n + 1 (+ odd)

Questo può quindi essere riscritto come:

f(n) = odd(n) * n + sign(n)

dove odd(n)ritorna 1per i numeri dispari e -1per i numeri pari.

Ci sono 4 soluzioni in totale:

f(n) = odd(n) * n + sign(n)  (edge cases: f(f(0))  -> -2, f(f(INT_MAX))   -> -8)
f(n) = even(n) * n - sign(n) (edge cases: f(f(0))  -> -2, f(f(INT_MIN+1)) -> -6)
f(n) = odd(n) * n - sign(n)  (edge cases: f(f(1))  -> -3, f(f(INT_MIN))   -> -5)
f(n) = even(n) * n + sign(n) (edge cases: f(f(-1)) -> -1, f(f(INT_MIN))   -> -5)

INT_MINpotrebbe sempre essere considerato un caso limite in tutte e 4 le funzioni come -INT_MIN == INT_MIN=> f(f(INT_MIN)) = INT_MIN.


Questo è essenzialmente lo stesso della mia risposta GolfScript (tranne spiegato meglio). Funziona con 0?
Ben Reich,

@BenReich Come indicato nella risposta, non funziona per 0altri 3 numeri.
Tyilo,

1
@Tylio vedo ora. Ha senso. Sembra che dovresti prendere il Zbonus solo se copri 0, almeno.
Ben Reich,

@BenReich Rimosso il bonus finché non lo avrò risolto.
Tyilo,

9

Ecco il mio tentativo.

long f(int i){return i;}
int f(long i){return -i;}

Esempio live :

int main()
{
  for(int i=-10; i<10; i=i+3)
    std::cout << f(f(i)) << "\n";
}

I tipi di input possono essere arbitrariamente personalizzati in base alle proprie esigenze. Questa versione funziona con valori letterali interi di dimensioni inferiori a 2 ^ 32-1.


2
Il problema ha detto f:Q->Q, no f:Z->Z.
AJMansfield,

@AJMansfield la sezione dei punteggi delle specifiche aveva lo scopo di offrire punti bonus per le funzioni definite f:Z->Z, scusate la formulazione confusa
ardnew,

6
il problema con questa risposta è che sembra definire due funzioni separate, mentre le specifiche richiedono di definirne solo una. ma non intendo iniziare un dibattito sulla semantica, è ancora una soluzione molto ponderata
ardnew,

@ardnew, oh hai ragione. Mi è stato fatto riferimento a questa valida obiezione solo pochi secondi prima di condividerla con la Lounge <C ++> sulla chat SO. Mi chiedo cosa ne faccia il compilatore (se non incorpora le chiamate), ma il mio assembly fa schifo.
rubenvb,

1
Penso che puoi rimuovere lo spazio inreturn -i
Cyoce

6

JavaScript, 18

f=n=>n%1?.5-n:n+.5

Utilizzando la nuova notazione con la freccia grassa (Firefox 22).

Altra versione (18):

f=n=>n%1?-.5/n:.5/n

Versione precedente (20):

f=n=>n-~~n?.5-n:n+.5

Esempio:

> [-3,-2,-1,1,2,3].map(f).map(f)
[3, 2, 1, -1, -2, -3]

10
Sembra che JavaScript si stia evolvendo in CoffeeScript.
Peter Taylor,

4

Mathematica 18

f=#+1/2-4#(#-⌊#⌋)&

Ecco ⌊...⌋la funzione piano. Utilizza solo numeri razionali (non elenchi, numeri complessi, ecc.)

f[10]
f[f[10]]

21/2

-10

f[-5]
f[f[-5]]

-9/2

5


3

linguaggio assembly x86 (FASM). L'argomento e il risultato sono nel registro eax.

Funziona correttamente per -2 ^ 30 <N <+ 2 ^ 30-1

Codice eseguibile di 16 byte.

        use32

f_n:
        lea     edx, [2*eax]
        xor     edx, eax
        btc     eax, 30
        shl     edx, 1
        jnc     .end
        neg     eax
.end:
        retn

Spuntare i tuoi numeri; 2E30 sarebbe 2 * 10 ^ 30, non 2 ^ 30 come penso tu voglia.
Nick T,

@NickT Il mio errore. Fisso.
johnfound,

Sono abbastanza sicuro che dovresti contare i byte nel codice sorgente.
nyuszika7h,

3

Lisp comune: 35 byte

(defun f(x)(/(if(> 1 x)-1/2 1/2)x))

Schema (e racchetta): 36 byte

(define(f x)(/(if(> 1 x)-1/2 1/2)x))

Ungolf con commenti e spiegazioni:

(define (f x)
  (/             ;; divide
     (if (> 1 x) ;; if x is below 1 
         -1/2    ;; then -1/2 (the fraction)
         1/2)    ;; else 1/2 (the fraction)
      x))        ;; gets divided with x

Per qualsiasi numero xin [1,->]la ifsi trasformerà nella frazione 1/2che è un vero e proprio numero esatto in entrambe le lingue.

La parte di divisione diventerà quindi (/ 1/2 x)così diventerà la frazione 1/(x*2)che è sempre sotto 1. Perché 1sarà 1/2, per 2esso 1/4, ecc.

Per qualsiasi numero inferiore all'1 il ifgirerà in alla frazione -1/2, che rende la funzione do (/ -1/2 x)che è -1/(2*x)ma poiché ci si può aspettare il valore da risultato della precedente esecuzione possiamo sostituire x per 1 / (x * 2) effettuare una doppia applicazione-1/((1/(x*2))*2) = -x

Ad esempio poiché 1si trasforma nella 1/2seconda applicazione(/ -1/2 1/2) ==> -1


Come funziona?
AJMansfield,

@AJMansfield ha aggiunto alcune informazioni. Basta chiedere se c'è qualcosa di poco chiaro. Leggere la sintassi LISP è come il greco se non l'hai imparato e ci vogliono alcune settimane per abituarti.
Sylwester,

3

C, 60 (⌈66 * .9⌉)

int f(int x){if(!x&1||!~x)return ~x;if(x<0)return x-1;return x+1;}

Ecco una versione senza licenza:

int f(int x){
    if(!x&1 || !~x) return ~x;
    if(x<0) return x-1;
    return x+1;
}

Questo metodo funziona usando solo numeri interi, quindi ottiene il bonus del 90%. Inizialmente lo stavo scrivendo in Java, ma mi sono reso conto che questo programma in particolare poteva beneficiare degli operatori logici in stile C.

Poiché non esiste un numero intero corrispondente -INT_MIN, f(f(INT_MIN))restituisce INT_MINinvece.

La mappatura sottostante è algebricamente piuttosto semplice. L'esecuzione dell'istruzione x=f(x)sostituisce x con:

  • x+1, se xè positivo e dispari
  • -x+1, se xè positivo e uniforme
  • x-1, se xè negativo e dispari
  • -x-1, se xè negativo e pari

Il risultato di ciascun caso rientrerà nel caso successivo la volta successiva che la funzione verrà applicata a x.

Come puoi vedere, la composizione di un caso con il caso successivo produce -x.

Il codice è il risultato di un'intelligente semplificazione della funzione per sfruttare la struttura a bit degli interi di complimento di due.


3

> <> , 21 + 3 = 24 byte, 22 punti

:0)$:0($:1$2%2*-*+-n;

Utilizzare l' interprete Python ufficiale e utilizzare l' -vopzione della riga di comando per immettere l'input, al costo di 3 byte.

Ho la sensazione che questo potrebbe essere migliore - continuerò a guardarlo e cercherò di giocare a golf.

Dato input n, il programma esce

(n>0) - ((n<0) + n * (1 - 2*(n%2)))

dove (n>0)e (n<0)sono booleani. Ciò equivale alla risposta Python di Gelatina

(n>0) - (n<0) - n * (-1)**n

ma ><>non ha un operatore di esponenziazione incorporato, quindi usiamo (1 - 2*(n%2))al posto di (-1)**n.

Ciò che segue è la teoria matematica: leggi se (e solo se) sei interessato:

Dato qualsiasi funzione f: Z -> Ztale che f(f(n)) = -nper tutti nin Z, si vede subito che f(f(f(f(n)))) = n, o in altre parole, f^4è la funzione identità. In particolare, fè invertibile e la sua funzione inversa è f^3. Così fè una permutazione Z, e poiché f^4 = Id, ne consegue che ogni orbita (o ciclo) del fha dimensioni sia 1, 2o 4.

Successivamente, lo vediamo f(0) = 0. Prova: f(0) = f(-0) = f(f(f(0))) = -f(0)così f(0) = 0, come desiderato. Al contrario, supponiamo che xsia in un ciclo di lunghezza 1o 2così f(f(x)) = x. Allora -x = xcosì x = 0.

Pertanto fè composto interamente da 4 cicli, ad eccezione del punto fisso (1 ciclo) in 0.

Inoltre, ogni 4-ciclo deve avere la forma (x, y, -x, -y), e ruotando il ciclo attorno possiamo supporre che xe ysono entrambi positivi. Al contrario, ogni prodotto di questo tipo di partizione a 4 cicli degli interi diversi da zero determina una scelta di f.

Pertanto, ogni scelta di fcorrisponde in modo univoco a un grafico diretto i cui vertici sono numeri interi positivi, in modo tale che ogni vertice è incidente esattamente con una freccia, sia entrando che uscendo. Più precisamente, nel grafico non orientato sottostante, ogni vertice ha esattamente il grado 1. (Ogni 4 cicli (x y -x -y)con xe ypositivo corrisponde alla freccia x --> y.)

La funzione di questa risposta (e diverse altre risposte qui) corrisponde al grafico in cui 1 --> 2, 3 --> 4e in generale 2k-1 --> 2k.

Tali grafici sono in corrispondenza biunivoca con infinite sequenze di coppie ordinate (a_n, p_n), in cui ogni a_nè un numero intero positivo e ciascuno p_nè o 0o 1: data una sequenza (a_1, p_1), (a_2, p_2), (a_3, p_3), ..., abbiamo prima coppia 1con 1 + a_1, e poi si formano sia la freccia 1 --> 1 + a_1o la freccia 1 + a_1 --> 1seconda se p_1è 0o 1. In sostanza, la freccia è o un <segno o un >segno, a seconda della parità di p_1.

Quindi, prendi il più piccolo intero positivo non accoppiato ke conta da k, esattamente a_2passi, SALTO di qualsiasi numero che è già associato a qualcosa. Associa kal risultato e imposta la direzione della freccia in base a p_2come sopra. Quindi ripetere con (a_3, p_3), ecc.

Ogni freccia verrà infine determinata in questo modo, quindi il processo è ben definito. La funzione in questa risposta corrisponde alla sequenza (1,0), (1,0), (1,0), ..., poiché al passo nil numero intero non accoppiato più piccolo è 2n-1e nessun numero intero più grande di quello che 2n-1è stato accoppiato con qualsiasi cosa, quindi otteniamo 2n-1 --> 2nper ciascuno n(le frecce sono orientate in questo modo perché ognuna è p_nuguale 0).

La cardinalità di questo set è (N*2)^N = N^N, che nell'ultimo paragrafo di questa risposta è uguale 2^Nalla cardinalità dei numeri reali.


Le opzioni della riga di comando sono in genere un byte ciascuna.
gatto

@cat Vedi la sezione "Invocazioni speciali" in questo meta post .
Mathmandan,

2

Per correggere la precedente risposta J (non ho abbastanza reputazione per commentare l'originale):

(*+[*1-~2*2|])

Sostituisce semplicemente il _1&^con 1-~2*2|], che dà il segno opposto. Quindi ho cambiato il carattere -in +(che conta solo sull'input di 1e _1).

Ecco i test:

   (*+[*1-~2*2|])6 3 _9 _8 1r2 _4.6 0 1 _1
7 _2 8 _9 1 7.28 0 2 _2
   (*+[*1-~2*2|])7 _2 8 _9 1 7.28 0 2 _2
_6 _3 9 8 0 _10.3568 0 _1 1

   NB. f^:2 = f@:f
   (*+[*1-~2*2|])^:(2)6 3 _9 _8 1r2 _4.6 0 1 _1
_6 _3 9 8 2 _5.0832 0 _1 1

Come puoi vedere, il dominio e l'intervallo sono di tutti i numeri reali, ma funziona solo per numeri interi (incluso 0).

Spiegazione:

(   *     + [ *  1-~    2*     2|]    )
 signum n + n * pred (twice (n mod 2))

2

GolfScript ceiling(26*.9)=24

Golfscript gestisce solo numeri interi, quindi applica il Zbonus per un totale di 24 punti:

.{..0>2*(\)2%!2*(@*+}{ }if

Il caso speciale di 0 rappresenta 8 caratteri. Ignorando 0, possiamo avere una risposta di 17 punti:

..0>2*(\)2%!2*(@*+

Questo codice esegue quanto segue su un numero intero xin cima allo stack:

  • Se xè 0, lascia 0in pila e non applica più regole.
  • Se xè pari, nega x.
  • Se xè positivo, aggiungi 1.
  • Se xè negativo, sottrai 1.

Ciò collega logicamente insiemi di 4 numeri in un ciclo, in cui fattraversa elementi del ciclo e gli angoli opposti del ciclo sono negativi l'uno rispetto all'altro. Ogni numero intero fa parte esattamente di 1 di tali cicli, tranne 0 che è il caso speciale. Ad esempio, per {-8, -7, 7, 8}:

  • 7 f -> 8
  • 8 f -> -7
  • -7 f -> -8
  • -8 f -> 7

Gli unici casi di test rilevanti che mi sono venuti in mente sono stati negativi pari, negativi pari, positivi pari, positivi pari 0, e poi mi sono buttato dentro -1e 1poiché la loro vicinanza 0potrebbe aver causato problemi:

[-10 -5 -1 0 1 5 10]
{.{..0>2*(\)2%!2*(@*+}{ }if}:f;
{f f}%
-> [10,5,1,0,-1,-5,-10]

Sono sicuro che l'attuale GolfScript può essere leggermente migliorato. Non sembra che dovrebbe contenere 26 caratteri! Mi piacerebbe sentire alcuni suggerimenti.


2

Java, solo per divertimento

Ecco un'implementazione che fa un'effettiva biiezione tra ℤ e ℤ², che è una funzione dispari allo stesso tempo (g (-x) == -g (x)). Tratta l'elemento ℤ² corrispondente come un numero complesso e lo moltiplica per "i", quindi converte nuovamente in ℤ.

f (x) = g⁻¹ (ig (x))
f (f (x)) = g⁻¹ (-g (x)) = - x

La funzione viene eseguita in O (1).

public class Ffn {
    public static int f(int n) {
        if (n == 0) {
            return 0;
        }
        // adjust sign
        int s = n > 0 ? 1 : -1;
        int m = n * s;
        // calculate square "radius"
        int r = (int) (Math.sqrt(2 * m - 1) + 1) / 2;
        int q = r * 2;
        // starting point
        int x = r, y = r;
        int k = q * (r - 1) + 1;

        if (m - k < q) {
            // go left
            x -= m - k;
        }
        else {
            // go left
            x -= q;
            // go down
            y -= m - k - q;
        }

        // multiply by i
        int x2 = -y * s, y2 = x * s;
        // adjust sign
        s = y2 < x2 || y2 == x2 && x2 < 0 ? -1 : 1;
        x2 *= s;
        y2 *= s;

        if (y2 == r) {
            // go left
            k += r - x2;
        }
        else {
            // go left and down
            k += q + r - y2;
        }
        return k * s;
    }

    public static void main(final String... args) {
        for (int i = 0; i < 1000000; ++i) {
            if (f(f(i)) != -i || f(f(-i)) != i) {
                System.out.println(i);
            }
        }
    }
}

PS Felice Anno Nuovo!


Credo che lo spazio bianco non sia necessario.
pepery

2

Python 3 - 38

Simile alla risposta di @ moose, ma f(n) == n. Funziona per tutti i valori interi.

f=lambda x:x*(isinstance(x,int)*2.0-1)

2

Perl, 33 (non spazi bianchi)

sub f{($=)=@_;$=-$_[0]?-$=:"$=.1"}

Modificare:

  • $=.".1"abbreviato in "$=.1"(grazie ardnew).

Matematica:

Matematica

Ungolfed:

# script.pl
sub f {
  ($=) = @_;   # short for $= = int($_[0]); 
               # "int" is implicit in assignments to $=;
               # ($=) can be prepended by "local" to get
               # the function free of side effects.

  $= - $_[0] ? # short for $= != $_[0], check if input is integer
    -$=        # input is not an integer  
  : $= . ".1"  # input is integer
}  

# Testing
chomp;
$_ = sprintf "f(f($_)) = f(%s) = %s\n", f($_), f(f($_));

Esempi:

perl -p script.pl
7
f(f(7)) = f(7.1) = -7
2
f(f(2)) = f(2.1) = -2
0
f(f(0)) = f(0.1) = 0
-1
f(f(-1)) = f(-1.1) = 1
-10
f(f(-10)) = f(-10.1) = 10
-1.23
f(f(-1.23)) = f(1) = 1.1
3.4
f(f(3.4)) = f(-3) = -3.1
1.0
f(f(1.0)) = f(1.1) = -1

soluzione solida: i casi di test in virgola mobile che non si dimostrerebbero per specifica (per questo avrebbero dovuto offrire punti bonus!). ecco il tuo stesso algoritmo con alcune pulizie in arrivo a 22 caratteri:sub f{yzxzzc?-$_:x.$_}
ardnew

1
@ardnew: grazie. Ma non sono d'accordo sul fatto che la tua soluzione usi lo stesso algoritmo. L'algoritmo nonsub f{yzxzzc?-$_:x.$_} è privo di stato, utilizza uno stato tramite la variabile . Per questo motivo , non è più una funzione (in senso matematico), poiché sono possibili valori diversi per lo stesso valore di input a seconda dello stato (il tempo contiene un o meno). Il mio algoritmo non utilizza uno stato, Le informazioni sono codificate nel valore di output. I numeri interi vengono convertiti in numeri reali aggiungendo . E i numeri reali vengono riconvertiti in numeri interi con il segno commutato. $_f$_x.1
Heiko Oberdiek,

interessante- nessun dato sullo stato viene utilizzato nella tua implementazione a causa dell'assegnazione iniziale e non a causa di alcune proprietà speciali di $=?
Ardnew,

non mi rendevo conto di aver fallito anche il mio requisito (che deve fessere definito Q->Q) con quel xcarattere. inoltre $=.".1"può essere abbreviato in"$=.1"
ardnew il

@ardnew: la proprietà speciale di $=è solo che richiede solo numeri interi. Lo stesso può essere raggiunto utilizzando una variabile normale: $a=int$_[0]. Ma questo costa tre byte aggiuntivi a causa della funzione int.
Heiko Oberdiek,

2

Julia, 26 anni

julia> f(n::Int)=n//1
f (generic function with 1 method)
julia> f(n)=int(-n)
f (generic function with 2 methods)
julia> f(f(4))
-4

Non super competitivo, ma molto giuliano poiché si basa su spedizioni multiple. Fa solo na Rational se è un Int, o un int con un segno meno se è qualcos'altro. Si potrebbe obiettare che si tratta di 2 funzioni, ma Julia considera questa una funzione con due metodi, ed equivale a definire una funzione con una istruzione if sul tipo di n.


Non è ciò che un matematico chiamerebbe una funzione: in Julia 3==3//1ritorna truema f(3//1)==f(3)ritorna false.
Omar,

2

Candy , 20 18 byte

Usa il trucco 3 -> 4 -> -3 -> -4 -> 3.

~A2%{|m}1A0>{+|-}.

Per invocarlo usa l'opzione -i sull'interprete

Esempio di doppio invocazione:

$ candy -i 7 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> 8
$ candy -i 8 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> -7
$ candy -i -7 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> -8
$ candy -i -8 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> 7

Forma lunga:

peekA
pushA
digit2
mod          # even/odd
if
else
  negate     # negate even numbers
endif
digit1
pushA
digit0
greater      # positive/negative
if
  add        # add two numbers from stack (original stack value, and delta)
else
  sub        # diff two numbers from stack (original stack value, and delta)
endif
retSub

2

Dyalog APL, 9 punti

×-⍨⊢ׯ1*⊢

La fonte è lunga 9 byte e si qualifica per il bonus (che non aiuta affatto). Utilizza anche la formula dalla risposta SO in alto.




1

Java, 113 byte

L'approccio è piuttosto semplice. È finito più byte di quanto mi aspettassi, ma può forse essere un po 'ridotto.

public class F{public static int f(int x){if(x<0)x+=-2147483647-++x;x+=1073741824;return x<0?-2147483647-++x:x;}

Fondamentalmente crea 4 diverse "aree" di x, utilizzando il fatto che Java lascia felicemente avvolgere le variabili. Ho dovuto fare una conversione complicata per i numeri negativi, che è la ragione principale per cui è finito più grande del previsto.

Funziona per tutti x oltre a -2147483648.


1

Stessa sequenza di numeri (3, 4, -3, -4, 3 ...) della risposta golfscript, ma implementata in perl (42 caratteri dopo che gli spazi bianchi sono stati rimossi)

sub f{($_[0]%2?1:-1)*$_[0]+($_[0]<0?-1:1)}

Più leggibilmente:

sub f { ($_[0] % 2 ? $_[0] : -$_[0] ) + ( $_[0] < 0 ? -1 : 1 ) }

O ancora più leggibile:

sub f {
  my $n = shift;
  my $sign = $n >= 0 ? 1 : -1;
  # note that in perl $n % 2 is the same as int($n) % 2
  if( $n % 2 ) {
    # odd: add one to magnitude
    return $n + $sign
  } else {
    # even: subtract one from magnitude then invert
    return -($n - $sign)
  }
}

Produzione:

ski@anito:~/mysrc/.../acme$ echo 3 | perl -e 'sub f{($_[0]%2?1:-1)*$_[0] + ($_[0]<0?-1:1)}; my $x = <>; for(0..10) { print "$_: $x\n"; $x = f($x); }'
0: 3
1: 4
2: -3
3: -4
4: 3
5: 4
6: -3
7: -4
8: 3
9: 4
10: -3

Quanto sopra funziona anche per i non interi: ski @ anito: ~ / mysrc /.../ acme $ echo 1.1234 | perl -e 'sub f {($ _ [0]% 2? 1: -1) * $ _ [0] + ($ _ [0] <0? -1: 1)}; my $ x = <>; per (0..4) {stampa "$ _: $ x \ n"; $ x = f ($ x); } '0: 1.1234 1: 2.1234 2: -1.1234 3: -2.1234 4: 1.1234
skibrianski

1

Sed, 25 byte.

|sed s/0+/0-/|sed s/^/0+/

Uso:

$ echo 1.23 |sed s/0+/0-/|sed s/^/0+/
0+1.23
$ echo 0+1.23 |sed s/0+/0-/|sed s/^/0+/
0+0-1.23

1

Matlab, 26 caratteri

f=@(n) (n<0)-(n<0)-n*(-1)^n

2
Questa non è una risposta valida, poiché il dominio e il codice della funzione non devono essere complessi.
Wrzlprmft,

oh, mi dispiace ... ho appena letto il titolo e non sono stato così attento ... Vediamo se riesco a modificarlo in qualche modo
bla

1

C ++ - 63 55,8

Ecco come appare il codice:

int f(int n){return (n&45056?n^45056:n|45056)*(n&45056?-1:1);}

Non funziona su numeri interi il cui quarto byte è uguale a 0xB poiché utilizza quel valore per tenere traccia dei passaggi. Altrimenti funziona su qualsiasi membro di Z, incluso zero.


puoi spiegarlo? a prima vista sembra che tu stia mantenendo un contatore di chiamate fcon una variabile statica. ma allora qual è il punto di sqrt?
Ardnew,

Mi sembra di aver frainteso la domanda; pensavo che una variabile statica andasse bene poiché C ++ è un linguaggio orientato allo stack, ma riparerò il codice. Altrimenti non ho idea del motivo per cui avevo bisogno sqrtin quanto viene arrotondato comunque con il cast di tipo. Rifatterò in modo che funzioni senza la variabile statica.
Darkgamma,

Non ho idea di dove tu abbia preso il 55.8, ma il tuo codice attuale è lungo 62 byte. Modifica: non importa, non ho letto correttamente la domanda.
nyuszika7h,

La limitazione che il quarto byte non può eguagliare 0xB purtroppo rende questa non una risposta valida alla sfida, che richiede che funzioni su (almeno) tutti i numeri interi.
pepery

1

Aggiornato con la funzione fornita da Synthetica (ovviamente quello che dovrebbe ottenere credito per questo ora)

Lingua: Python

Numero di caratteri: 41 incluso spazi bianchi

f=lambda x:-float(x) if str(x)==x else`x`

Fornisci anche il nome della lingua utilizzata e fornisci anche il conteggio dei caratteri.
Programma FOX il

Mi piace come funziona anche con numeri non interi. Molto bene. :)
cjfaure,

f=lambda x:-float(x) if str(x)==x else`x`è un po 'più breve: 41 compresi gli spazi bianchi
Aprıʇǝɥʇuʎs

Grazie Synthetica, non sapevo nemmeno del trucco dei bastoncini! : D
HolySquirrel,

Sui numeri interi frestituisce una stringa; la specifica dice che deve restituire un numero razionale.
Omar,

1

Prolog, 36 byte

Codice:

X*Y:-X//1=:=X,Y is 0.5+X;Y is 0.5-X.

Ha spiegato:

Dyadic predicate which converts integers to floats and floats back to negated integers.

Esempio:

10*X.
X = 10.5

10*Y,Y*X.
X = -10,
Y = 10.5


1

Mouse-2002 , 21 19 12 byte

$A1%[1%_|1%]

Definisce una funzione A; chiamalo come #A,#A,?;;(che attenderà che l'utente inserisca un numero qualsiasi). In alternativa, chiamalo come #A,#A,n;;dove si ntrova qualsiasi numero.


1

Julia, 21

f(x)=(1-2(1>x>-1))/2x

Poi

julia> f(f(12//1))
-12//1

p // q è la notazione letterale di julia dei numeri razionali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.