Définir une fonction f telle que f (f (n)) = -n pour tous les entiers non nuls n

43

Ce défi a été inspiré par un blog de programmation que je fréquente. S'il vous plaît voir le post original ici: Un puzzle de programmation


Défi

Définissez une fonction f:Q->Qtelle que f(f(n)) = -npour tous les entiers non nuls n, et où Qest l'ensemble des nombres rationnels.

Détails

Quelle que soit la langue que vous préférez, s'il vous plaît définir une fonction ou d'un programme fqui accepte comme paramètre un nombre net retourne ou émet un numéro f(n).

Les entrées peuvent être fournies par le mécanisme le plus naturel pour votre langage: argument de fonction, lecture depuis STDIN, argument de ligne de commande, position de la pile, entrée vocale, signes de groupe, etc.

La sortie doit être une valeur renvoyée par une fonction / un programme ou imprimée sur STDOUT.

J'aimerais limiter les réponses aux fonctions qui ne tirent pas parti de l'état du programme ou de la mémoire globale / des données visibles de l'extérieur de la fonction f. Par exemple, garder un compteur en dehors de fcela compte combien de fois a fété appelé et faire une négation basée sur ce compte n'est pas très difficile ou intéressant pour personne. Les décisions prises fne doivent s’appuyer que sur des données fcomprises dans la portée lexicale.

Cependant, cette restriction est probablement inappropriée pour certains langages orientés pile ou d'autres types de langages qui ne distinguent pas ces types de données ou de portées. S'il vous plaît utilisez votre meilleur jugement pour rester dans l'esprit de ce défi.


Notation

Les règles de golf communes au code s'appliquent - votre score est le nombre d' octets dans votre code source.

La réponse minimale nécessite que le domaine et le codomaine de fsoient un sous-ensemble des rationnels Q. Si vous limitez votre domaine et votre codomaine faux entiers Z, votre score correspond au plafond de 90% du nombre d' octets de votre code source.

Jeu décisif

En cas d'égalité, les éléments suivants seront utilisés dans l'ordre:

  1. Le plus petit nombre de symboles imprimables non-d'espaces blancs dans votre code source
  2. Date et heure de soumission de la réponse au plus tôt

modifier

Vous n'êtes pas obligé de prendre en charge des nombres de taille arbitraire. Veuillez interpréter les ensembles Zet Qles types de données dans la langue de votre choix (généralement des nombres entiers et des nombres à virgule flottante, respectivement).

Si votre solution repose entièrement sur la structure sous-jacente ou le modèle de bits d'un type de données, décrivez-en les limites et son utilisation.

ardenne
la source
20
f (n) = i * n - mathématiques pures: P
Johannes Kuhn
8
@JohannesKuhn c'est pourquoi le domaine et codomaine sont limitées aux rationals
ardnew
Pourriez-vous expliquer ce que f:Q->Qsignifie?
beary605
@ beary605 cela signifie fest une fonction mappant les membres de Q(nombres rationnels) sur les autres membres (éventuellement les mêmes) de Q. voir en.wikipedia.org/wiki/Function_(mathematics)#Notation
ardnew
7
Je savais que j'avais vu cela récemment, mais il m'a fallu un certain temps pour me rappeler où. Une version moins précisément spécifiée sur StackOverflow a été récemment fermée. Plus de 100 réponses.
Peter Taylor

Réponses:

12

J, 9 points (10 caractères)

Basé sur la réponse stackoverflow :

   (*-[*_1&^)

Première idée (13 caractères):

   ((-*)-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
randomra
la source
Cela fonctionne pour une entrée entière, mais cela produit une sortie imaginaire pour des valeurs à virgule flottante (la fonction doit produire une sortie rationnelle pour une entrée rationnelle conformément à la spécification)
Volatility
5
@Volatility, la spécification est confuse, mais sa lecture permet de restreindre le domaine et la codomaine aux entiers.
Peter Taylor
Avez-vous besoin des parenthèses?
Cyoce
14

Python: 61 34 30 29 27 points

f: Q -> Q

en maths:

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

en Python:

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

testé avec

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

logique derrière ceci:

Lorsque vous prenez un entier net le mettez dans fvous obtiendrez x+0.5. Ce n'est plus un entier, donc la prochaine application sera ce 0.5-(x+0.5)qui est -x.

Crédits

Grâce à

  • Bakuriu pour l'avoir rayé de 61 à 34 caractères.
  • Volatilité pour réduire davantage la taille du code à 30 caractères.
  • copie pour réduire la taille du code à 29 caractères (et pour résoudre un problème potentiel en virgule flottante).
  • aditsu pour avoir mentionné une incohérence liée aux modifications ci-dessus.

Remarques

D'abord j'ai pensé que ça irait

f = lambda n: 1j*n

mais son f: N-> C et qui n'est pas autorisé: - /

Martin Thoma
la source
1
Peut être réduit à: f=lambda x:x%1>0and(-x+x%1)or x+.1ce qui ne fait que 34 caractères.
Bakuriu
f=lambda x:[x+.1,x%1-x](x%1>0)a seulement 30 ans
Volatilité
1
Un caractère à plus court: f=lambda x:[x+.5,.5-x][x%1>0]. Notez l'utilisation de .5 au lieu de .1 pour résoudre les problèmes de précision
copier le
1
@AJMansfield 1.48 n'est pas un entier.
Martin Thoma
1
Non, ça ne veut pas dire ça. S'il en parle, il aurait dû écrire "tous les nombres rationnels". f:Q->Qsignifie simplement que f mappe un nombre rationnel à un nombre rationnel. Ce que ma définition de f fait.
Martin Thoma
11

C, 41 points (41 ou 45 caractères)

Fonctionne en 32 et 64 bits.

f : Z -> Z(sauf INT_MAX):

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

Si nous n'avons pas à inclure, 0nous pouvons éliminer quelques caractères (41 caractères):

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

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

Cette fonction fonctionne en divisant tous les nombres entiers en 4 groupes en fonction de leur signe et de leur parité.

Nous avons donc 4 combinaisons différentes:

+ even, + odd, - even, - odd

Comme nous devons changer le signe du nombre, mais pas la parité après deux passages, nous obtenons deux séquences différentes possibles:

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

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

Dans cet exemple, j'ai choisi le premier.

Nous devons d’abord mapper tous les entiers même positifs aux impairs négatifs. Nous faisons cela en changeant le signe et en incrémentant le nombre (vous pouvez également choisir de décrémenter le nombre à la place):

f1(n) = -n + 1

Nous devons ensuite mapper tous les entiers négatifs impairs sur des entiers même négatifs. Nous devons nous assurer que f2(f1(n)) = -n:

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

En utilisant les mêmes méthodes, nous trouvons f3et f4:

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

Pour combiner ces fonctions en une seule fonction, nous observons que chaque fois que nnous sommes même, nous inversons le signe de net que chaque fois que nnous sommes positifs, nous incrémentons de un et sinon nous décrémentons de un:

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

Ceci peut donc être réécrit comme:

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

odd(n)renvoie 1les nombres impairs et les nombres -1pairs.

Il y a 4 solutions au total:

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_MINpeut toujours être considéré comme un cas de bordure dans les 4 fonctions comme -INT_MIN == INT_MIN=> f(f(INT_MIN)) = INT_MIN.

Tyilo
la source
Ceci est essentiellement le même que ma réponse GolfScript (sauf mieux expliqué). Est-ce que ça marche pour 0?
Ben Reich
@BenReich Comme indiqué dans la réponse, cela ne fonctionne pas 0avec 3 autres chiffres.
Tyilo
1
@Tylio je vois maintenant. Logique. Il semble que vous ne devriez prendre le Zbonus que si vous couvrez au moins 0.
Ben Reich
@BenReich Supprimez le bonus jusqu'à ce que je le répare.
Tyilo
9

Voici mon coup d'oeil.

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

Exemple en direct :

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

Les types de saisie peuvent être arbitrairement adaptés à vos besoins. Cette version fonctionne pour les littéraux entiers de magnitude inférieure à 2 ^ 32-1.

Rubenvb
la source
2
Le problème dit f:Q->Q, pas f:Z->Z.
AJMansfield
@AJMansfield la section de notation de la spécification était censée offrir des points bonus pour les fonctions définies f:Z->Z, désolé pour la formulation déroutante
ardnew
6
Le problème avec cette réponse est qu'il semble définir deux fonctions distinctes, alors que la spécification exige que vous n'en définissiez qu'une. mais je ne veux pas commencer un débat sémantique, c'est toujours une solution très réfléchie
ardnew
@ardnew, oh tu as raison. Il ne m'a fallu que quelques secondes pour signaler cette objection valide avant de la partager avec le Lounge <C ++> sur le chat SO. Je me demande ce que le compilateur en fait (s’il ne met pas les appels en ligne), mais mon assemblage est nul.
rubenvb
1
Je pense que vous pouvez supprimer l'espacereturn -i
Cyoce
6

JavaScript, 18

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

Utilisation de la nouvelle notation grosse flèche (Firefox 22).

Autre version (18):

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

Version précédente (20):

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

Exemple:

> [-3,-2,-1,1,2,3].map(f).map(f)
[3, 2, 1, -1, -2, -3]
copie
la source
10
On dirait que JavaScript est en train de devenir CoffeeScript.
Peter Taylor
4

Mathematica 18

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

Voici ⌊...⌋la fonction de sol. Il utilise uniquement des nombres rationnels (pas des listes, des nombres complexes, etc.)

f[10]
f[f[10]]

21/2

-dix

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

-9/2

5

Ybeltukov
la source
3

Langage d'assemblage x86 (FASM). L'argument et le résultat sont dans le registre eax.

Cela fonctionne correctement pour -2 ^ 30 <N <+ 2 ^ 30-1

Code exécutable de 16 octets.

        use32

f_n:
        lea     edx, [2*eax]
        xor     edx, eax
        btc     eax, 30
        shl     edx, 1
        jnc     .end
        neg     eax
.end:
        retn
johnfound
la source
Nitpicking vos numéros; 2E30 serait 2 * 10 ^ 30, pas 2 ^ 30 comme je pense que vous voulez.
Nick T
@ NickT Mon erreur. Fixé.
johnfound
Je suis sûr que vous êtes censé compter les octets dans le code source.
nyuszika7h
3

Common Lisp: 35 octets

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

Schéma (et raquette): 36 octets

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

Ungolfed avec des commentaires et des explications:

(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

Pour n'importe quel nombre xdans [1,->]le ifdeviendra la fraction 1/2qui est un nombre exact exact dans les deux langues.

La partie de division deviendra alors, de (/ 1/2 x)sorte que la fraction deviendra 1/(x*2)qui est toujours en dessous 1. Car 1ce sera 1/2, pour 2c'est 1/4, etc.

Pour tout nombre inférieur à 1, la iffraction sera renvoyée -1/2, ce qui rend la fonction do, (/ -1/2 x)ce qui est vrai, -1/(2*x)mais puisque nous pouvons nous attendre à ce que la valeur soit le résultat de l'exécution précédente, nous pouvons remplacer x par 1 / (x * 2) en effectuant une double application.-1/((1/(x*2))*2) = -x

Par exemple , depuis 1tours dans 1/2la seconde application est(/ -1/2 1/2) ==> -1

Sylwester
la source
Comment cela marche-t-il?
AJMansfield
@AJMansfield a ajouté quelques informations. Il suffit de demander s'il y a quelque chose d'incertain. Lire la syntaxe LISP ressemble au grec si vous ne l’avez pas appris et qu’il faut quelques semaines pour s’y habituer.
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;}

Voici une version non condensée:

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

Cette méthode utilise uniquement des nombres entiers, ce qui lui donne le bonus de 90%. Je l’écrivais à l’origine en java, mais j’ai réalisé que ce programme en particulier pourrait tirer parti des opérateurs logiques de type C.

Comme il n'y a pas d'entier correspondant à -INT_MIN, f(f(INT_MIN))retourne à la INT_MINplace.

La cartographie sous-jacente est algébriquement plutôt simple. L'exécution de l'instruction x=f(x)remplace x par:

  • x+1, si xest positif et impair
  • -x+1, si xest positif et même
  • x-1, si xest négatif et impair
  • -x-1, si xest négatif et même

Le résultat de chaque cas tombera dans le cas suivant la prochaine fois que la fonction sera appliquée à x.

Comme vous pouvez le constater, la composition d’une affaire après celle-ci cède -x.

Le code est le résultat d'une simplification astucieuse de la fonction pour tirer parti de la structure en bits des entiers complémentaires à deux.

AJMansfield
la source
3

> <> , 21 + 3 = 24 octets, 22 points

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

Utilisez l' interpréteur Python officiel et utilisez l' -voption de ligne de commande pour saisir l'entrée, au coût de 3 octets.

J'ai le sentiment que cela pourrait être mieux - je vais continuer à regarder et essayer de jouer au golf.

Compte tenu des entrées n, les résultats du programme

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

(n>0)et (n<0)sont des booléens. Cela équivaut à la réponse en gélatine Python

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

mais ><>n'a pas d'opérateur d'exponentiation intégré, nous utilisons donc (1 - 2*(n%2))à la place de (-1)**n.

Ce qui suit est la théorie mathématique - lisez si (et seulement si) vous êtes intéressé:

Compte tenu de toute fonction f: Z -> Ztelle que f(f(n)) = -npour tous ndans Z, on voit immédiatement que f(f(f(f(n)))) = n, autrement dit, f^4est la fonction d'identité. En particulier, fest inversible, et sa fonction inverse est f^3. Ainsi fest une permutation Z, et depuis f^4 = Id, il suit que chaque orbite (ou cycle) de fla taille a été soit 1, 2ou 4.

Ensuite, nous voyons ça f(0) = 0. Preuve:, f(0) = f(-0) = f(f(f(0))) = -f(0)donc f(0) = 0, comme vous le souhaitez. Inversement, supposons qu’il s’agisse xd’un cycle de longueur 1ou 2alors f(f(x)) = x. Alors -x = xoui x = 0.

Ainsi fest entièrement constitué de 4 cycles, sauf pour le point fixe (1 cycle) à 0.

De plus, tous les 4 cycles doivent avoir la forme (x, y, -x, -y), et en tournant le cycle, nous pouvons supposer que xet ysont tous deux positifs. Inversement, chaque produit de 4 cycles partitionnant les entiers non nuls en détermine le choix f.

Ainsi, chaque choix de fcorrespond uniquement à un graphe dirigé dont les sommets sont les entiers positifs, de sorte que chaque sommet est incident pour exactement une flèche, qu'elle soit entrante ou sortante. Plus précisément, dans le graphe sous-jacent sous-jacent, chaque sommet a un degré exact 1. (Chaque cycle de 4 cycles (x y -x -y)avec xet ypositif correspond à la flèche x --> y.)

La fonction de cette réponse (et plusieurs autres réponses ici) correspond au graphique où 1 --> 2, 3 --> 4et en général 2k-1 --> 2k.

Ces graphiques sont en bijection avec des séquences infinies de paires ordonnées (a_n, p_n), où chacun a_nest un nombre entier positif et chacun p_nest soit 0ou 1: étant donné une séquence (a_1, p_1), (a_2, p_2), (a_3, p_3), ..., nous avons d' abord paire 1avec 1 + a_1, et ensuite on forme soit sur la flèche 1 --> 1 + a_1ou sur la flèche en 1 + a_1 --> 1fonction de si p_1est 0ou 1. Essentiellement, la flèche est soit un <signe, soit un >signe, en fonction de la parité de p_1.

Ensuite, prenez le plus petit entier positif non apparié k, et comptez à partir de k, pas à a_2pas, en sautant tout nombre déjà associé à quelque chose. Associez-vous kau résultat et définissez le sens de la flèche en fonction de ce p_2qui précède. Puis répétez avec (a_3, p_3), etc.

Chaque flèche sera éventuellement déterminée de cette façon, le processus est donc bien défini. La fonction dans cette réponse correspond à la séquence (1,0), (1,0), (1,0), ..., car au pas nle plus petit entier non apparié est 2n-1et aucun entier plus grand que ce qui 2n-1a été jumelé avec quoi que ce soit, nous obtenons donc 2n-1 --> 2npour chacun n(les flèches sont orientées de cette façon car chacun p_nest égal à 0).

La cardinalité de cet ensemble est (N*2)^N = N^Nce qui, au dernier paragraphe de cette réponse, égale 2^Nla cardinalité des nombres réels.

Mathmandan
la source
Les options de ligne de commande sont généralement un octet chacune.
Chat
@cat Voir la section "Invocations spéciales" de cette publication .
mathmandan
2

Pour corriger la réponse J précédente (je n'ai pas assez de réputation pour commenter l'original):

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

Il remplace simplement le _1&^avec 1-~2*2|], ce qui donne le signe opposé. J'ai donc changé le -en +(qui ne compte que pour l'entrée de 1et _1).

Voici les tests:

   (*+[*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

Comme vous pouvez le constater, le domaine et la plage sont tous des nombres réels, mais cela ne fonctionne que pour les entiers (y compris 0).

Explication:

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

GolfScript ceiling(26*.9)=24

Golfscript ne gère que les entiers, appliquez donc le Zbonus pour un total de 24 points:

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

Le cas particulier de 0 compte pour 8 caractères. En ignorant 0, nous pouvons avoir une réponse en 17 points:

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

Ce code a les effets suivants sur un entier situé xau-dessus de la pile:

  • Si la valeur xest 0, laissez 0sur la pile et n'appliquez plus de règles.
  • Si xest égal, nie x.
  • Si xest positif, ajouter 1.
  • Si xest négatif, soustrayez 1.

Cela connecte logiquement des ensembles de 4 nombres dans un cycle, où ftraverse des éléments du cycle, et les angles opposés du cycle sont des négatifs l'un par rapport à l'autre. Chaque entier fait partie de exactement 1 tel cycle, à l'exception de 0 qui est une casse spéciale. Par exemple, pour {-8, -7, 7, 8}:

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

Les seuls cas de test pertinents auxquels je pouvais penser étaient un négatif impair, négatif même, positif positif, positif positif 0, puis j'ai ajouté -1et 1vu que leur proximité 0peut avoir causé des problèmes:

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

Je suis sûr que le GolfScript réel peut être amélioré quelque peu. Il ne semble pas que cela devrait prendre 26 caractères! J'adorerais entendre des suggestions.

Ben Reich
la source
2

Java, juste pour le plaisir

Voici une implémentation qui effectue une bijection réelle entre ℤ et ℤ², qui est une fonction impaire en même temps (g (-x) == -g (x)). Il traite l'élément ² correspondant comme un nombre complexe et le multiplie par "i", puis le reconvertit en ℤ.

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

La fonction s'exécute en 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 bonne année!

Aditsu
la source
Je crois que les espaces sont inutiles.
pppery
2

Python 3 - 38

Semblable à la réponse de @ moose, mais f(n) == n. Fonctionne pour toutes les valeurs entières.

f=lambda x:x*(isinstance(x,int)*2.0-1)
cjfaure
la source
2

Perl, 33 (espace non blanc)

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

Modifier:

  • $=.".1"raccourci à "$=.1"(merci ardnew).

Math:

Math

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($_));

Exemples:

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
Heiko Oberdiek
la source
Solution robuste - les tests en virgule flottante que vous avez démontrés ne sont pas requis par spécification (aurait dû offrir des points bonus pour cela!). voici votre même algorithme avec quelques nettoyages entrant à 22 caractères:sub f{yzxzzc?-$_:x.$_}
ardnew
1
@ardnew: Merci. Mais je ne suis pas d'accord que votre solution utilise le même algorithme. L'algorithme sub f{yzxzzc?-$_:x.$_}n'est pas libre d'état, il utilise un état via la variable $_. De ce fait, fn’est plus une fonction (au sens mathématique), car différentes valeurs sont possibles pour la même valeur d’entrée en fonction de l’état (la météo $_contient un xou pas). Mon algorithme n'utilise pas d'état. Les informations sont codées dans la valeur de sortie. Les entiers sont convertis en nombres réels en ajoutant .1. Et les nombres réels sont reconvertis en nombres entiers avec le signe changé.
Heiko Oberdiek
intéressant- aucune donnée d'état n'est utilisée dans votre implémentation à cause de l'affectation initiale et non à cause d'une propriété spéciale de $=?
mardi
Je n'avais pas réalisé que j'avais également échoué avec mes propres exigences ( fà définir Q->Q) avec ce caractère x. aussi $=.".1"peut être raccourci à"$=.1"
ardnew
@ardnew: La propriété spéciale de $=est juste qu'elle ne prend que des nombres entiers. La même chose peut être réalisée en utilisant une variable ordinaire: $a=int$_[0]. Mais cela coûte trois octets supplémentaires à cause de la fonction int.
Heiko Oberdiek
2

Julia, 26 ans

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

Pas super compétitif, mais très julien puisqu'il repose sur plusieurs envois. Cela rend na rationnel si c'est un Int, ou un int avec un signe moins s'il s'agit de quelque chose d'autre. On pourrait objecter qu'il s'agit de 2 fonctions, mais Julia considère qu'il s'agit d'une fonction avec deux méthodes, ce qui revient à définir une fonction avec une instruction if sur le type de n.

gggg
la source
Ce n’est pas ce qu’un mathématicien appellerait une fonction: Julia 3==3//1retourne truemais f(3//1)==f(3)retourne false.
Omar
2

Candy , 20 18 octets

Utilise le tour 3 -> 4 -> -3 -> -4 -> 3.

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

Pour l'invoquer, utilisez le commutateur -i sur l'interpréteur

Exemple de double invocation:

$ 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

Forme longue:

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
Dale Johnson
la source
2

Dyalog APL, 9 points

×-⍨⊢ׯ1*⊢

La source a 9 octets de long et se qualifie pour le bonus (ce qui n’aide en rien). Il utilise également la formule de la première réponse SO.

lirtosiast
la source
1

GTB , 22

@S;N,"--$x?N)→N~N#~-N&
Timtech
la source
1

Java, 113 octets

L'approche est assez simple. Il a fini par avoir plus d'octets que je ne l'aurais prévu, mais peut-être un peu plus bas.

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

Il crée fondamentalement 4 "zones" différentes de x, en utilisant le fait que Java laisse heureusement les variables en vrac. J'ai dû faire une conversion délicate pour les nombres négatifs, ce qui est la raison principale pour laquelle cela a été plus important que prévu.

Fonctionne pour tous les x sauf -2147483648.

FIQ
la source
1

Même séquence de nombres (3, 4, -3, -4, 3 ...) que la réponse golfscript, mais implémentée en perl (42 caractères après la suppression des espaces)

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

Plus lisiblement:

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

Ou encore plus lisiblement:

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

Sortie:

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
skibrianski
la source
Ce qui précède fonctionne également pour les non-entiers: ski @ anito: ~ / mysrc /.../ acme $ echo 1.1234 | perl -e 'sous f {($ _ [0]% 2? 1: -1) * $ _ [0] + ($ _ [0] <0? -1: 1)}; mon $ x = <>; pour (0..4) {print "$ _: $ x \ n"; $ x = f ($ x); } '0: 1.1234 1: 2.1234 2: -1.1234 3: -2.1234 4: 1.1234
skibrianski
1

Sed, 25 octets.

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

Usage:

$ 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
Ken A
la source
1

Matlab, 26 caractères

f=@(n) (n<0)-(n<0)-n*(-1)^n
bla
la source
2
Ce n'est pas une réponse valable, car le domaine et la codomaine de la fonction ne doivent pas être complexes.
Wrzlprmft
oh, je suis désolé ... Je viens de lire le titre et je n’étais pas si prudent ... Voyons si je peux éditer ça un peu
bla
1

C ++ - 63 55.8

Voici à quoi ressemble le code:

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

Il ne fonctionne pas sur les entiers dont le quatrième octet est égal à 0xB car il utilise cette valeur pour garder une trace des passes. Sinon, fonctionne sur tout membre de Z, y compris zéro.

Darkgamma
la source
pouvez-vous expliquer celui-ci? lors de la première inspection, il semble que vous gardiez un compteur d'appels favec une variable statique. mais alors quel est le point de la sqrt?
lundi
Il me semble avoir mal compris la question. Je pensais qu’une variable statique était acceptable puisque C ++ est un langage orienté pile, mais je vais corriger le code. Sinon, je ne sais pas pourquoi j'ai eu besoin, sqrtcar il est arrondi de toute façon avec le casting. Je vais le refactoriser pour qu'il fonctionne sans la variable statique.
Darkgamma
Je ne sais pas d'où vous venez 55.8, mais votre code actuel est long de 62 octets. Edit: Peu importe, je n'ai pas lu la question correctement.
Nyuszika7h
La restriction selon laquelle le quatrième octet ne peut pas être égal à 0xB en fait malheureusement une réponse non valide au défi, ce qui nécessite de travailler sur (au moins) tous les entiers.
pppery
1

Mise à jour avec la fonction fournie par Synthetica (évidemment celui qui devrait en avoir le crédit maintenant)

Langue: Python

Nombre de caractères: 41 y compris les espaces

f=lambda x:-float(x) if str(x)==x else`x`
HolySquirrel
la source
Indiquez également le nom de la langue que vous avez utilisée et indiquez également le nombre de caractères.
ProgramFOX
J'aime la façon dont cela fonctionne également avec les non-entiers. Bien joué. :)
cjfaure
f=lambda x:-float(x) if str(x)==x else`x`est un peu plus court: 41, y compris les espaces blancs
lundi
Merci Synthetica, je ne connaissais même pas le truc des backticks! : D
HolySquirrel
On integers frenvoie une chaîne; le cahier des charges indique qu'il doit renvoyer un nombre rationnel.
Omar
1

Prolog, 36 octets

Code:

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

A expliqué:

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

Exemple:

10*X.
X = 10.5

10*Y,Y*X.
X = -10,
Y = 10.5
Emigna
la source
1

Javascript ES6, 27 26 octets

a=>a%1?-Math.floor(a):a+.2
SuperJedi224
la source
1

Mouse-2002 , 21 19 12 bytes

$A1%[1%_|1%]

Définit une fonction A; appelez-le comme #A,#A,?;;(ce qui attendra que l'utilisateur entre un nombre quelconque). Alternativement, appelez-le comme #A,#A,n;;nest n'importe quel nombre.

chat
la source
1

Julia, 21 ans

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

ensuite

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

p // q est la notation littérale de julia des nombres rationnels.

mschauer
la source