Defina uma função f tal que f (f (n)) = -n para todos os números inteiros diferentes de zero n


43

Esse desafio foi inspirado em um blog de programação que eu frequento. Veja o post original aqui: Um quebra-cabeça de programação


Desafio

Defina uma função f:Q->Qtal que f(f(n)) = -npara todos os números diferentes de zero ne onde Qestá o conjunto de números racionais.

Detalhes

Em qualquer idioma que você preferir, defina uma função ou programa fque aceite como parâmetro um número ne retorne ou produza um número f(n).

A entrada pode ser fornecida por qualquer mecanismo que seja mais natural para o seu idioma: argumento de função, leitura de STDIN, argumento de linha de comando, posição da pilha, entrada de voz, sinais de gangue, etc.

A saída deve ser um valor de retorno de uma função / programa ou impresso em STDOUT.

Gostaria de restringir respostas a funções que não tiram vantagem do estado do programa ou da memória / dados globais visíveis de fora da função f. Por exemplo, manter um contador fora do fque conta quantas vezes ffoi chamado e apenas fazer uma negação com base nessa contagem não é muito desafiador ou interessante para ninguém. As decisões tomadas fdevem depender apenas de dados dentro fdo escopo lexical.

No entanto, essa restrição provavelmente é inadequada para alguns idiomas orientados a pilha ou outros tipos de idiomas que não distinguem esses tipos de dados ou escopos. Por favor, use seu melhor julgamento para manter o espírito desse desafio.


Pontuação

Aplicam-se regras comuns de golfe com código - sua pontuação é o número de bytes no seu código-fonte.

A resposta mínima requer que o domínio e o codomain fsejam um subconjunto dos racionais Q. Se você restringir seu domínio e seu código faos números inteiros Z, sua pontuação será o limite de 90% do número de bytes no seu código-fonte.

Tiebreak

Em caso de empate, o seguinte será usado na ordem:

  1. Menor número de símbolos que não sejam espaços em branco para impressão no código-fonte
  2. Data e hora do envio da resposta mais cedo

Editar

Você não é obrigado a suportar números de tamanho arbitrário. Por favor, interprete os conjuntos Ze Qcomo tipos de dados no idioma escolhido (geralmente inteiro e ponto flutuante, respectivamente).

Se sua solução depende inteiramente da estrutura subjacente ou padrão de bits de um tipo de dados, descreva suas limitações e como está sendo usada.


20
f (n) = i * n - matemática pura: P
Johannes Kuhn

8
@JohannesKuhn é por isso que o domínio e contradomínio são restritas aos racionais
ardnew

Você poderia explicar o que f:Q->Qsignifica?
beary605

@ beary605 significa que fé uma função que mapeia membros de Q(números racionais) para outros membros (possivelmente o mesmo) de Q. veja en.wikipedia.org/wiki/Function_(mathematics)#Notation
ardnew

7
Eu sabia que tinha visto isso recentemente, mas demorou um pouco para lembrar onde. Uma versão menos rigorosamente especificada no StackOverflow foi fechada recentemente. Mais de 100 respostas.
Peter Taylor

Respostas:


12

J, 9 pontos (10 caracteres)

Com base na resposta do stackoverflow :

   (*-[*_1&^)

Primeira ideia (13 caracteres):

   ((-*)-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

Isto funciona para entrada inteiro, mas esta produz uma saída imaginária para valores de ponto flutuante (a função deve produzir uma saída racional para a entrada racional de acordo com a especificação)
Volatilidade

5
@ Volatility, a especificação é confusa, mas, enquanto eu a lê, permite restringir o domínio e o codomain a números inteiros.
Peter Taylor

Você precisa dos parênteses?
Cyoce

14

Python: 61 34 30 29 27 pontos

f: Q -> Q

em matemática:

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

em Python:

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

testado com

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

lógica por trás disso:

Quando você pega um número inteiro ne o coloca, freceberá x+0.5. Como não é mais um número inteiro, a próxima aplicação será 0.5-(x+0.5)qual é -x.

Créditos

Graças a

  • Bakuriu por reduzir de 61 para 34 caracteres.
  • Volatilidade para reduzir ainda mais o tamanho do código para 30 caracteres.
  • cópia para reduzir o tamanho do código para 29 caracteres (e corrigir um possível problema de ponto flutuante).
  • aditsu por mencionar uma inconsistência que veio com as alterações acima.

Notas

Primeiro eu pensei que isso seria ok

f = lambda n: 1j*n

mas é f: N-> C e isso não é permitido: - /


1
Pode ser reduzido para: f=lambda x:x%1>0and(-x+x%1)or x+.1que possui apenas 34 caracteres.
Bakuriu

f=lambda x:[x+.1,x%1-x](x%1>0)é apenas 30
Volatility

1
Um carbonizar mais curto: f=lambda x:[x+.5,.5-x][x%1>0]. Observe o uso de .5 em vez de .1 para solucionar problemas de precisão
copie

1
@AJMansfield 1.48 não é um número inteiro.
Martin Thoma

1
Não, isso não significa isso. Se ele mencionou isso, ele deveria ter escrito "todos os números racionais". f:Q->Qsignifica apenas que f mapeia o número racional para números racionais. Qual minha definição de f faz.
Martin Thoma 12/07

11

C, 41 pontos (41 ou 45 caracteres)

Funciona usando 32 e 64 bits.

f : Z -> Z(exceto INT_MAX):

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

Se não precisarmos incluir 0, podemos raspar alguns caracteres (41 caracteres):

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

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

Essa função funciona dividindo todos os números inteiros em 4 grupos, com base no sinal e na paridade.

Portanto, temos as 4 combinações diferentes:

+ even, + odd, - even, - odd

Como precisamos mudar o sinal do número, mas não a paridade após duas passagens, obtemos duas sequências possíveis diferentes:

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

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

Neste exemplo, eu escolhi o primeiro.

Primeiro, precisamos mapear todos os números inteiros positivos para números inteiros negativos. Fazemos isso alterando o sinal e incrementando o número (você também pode optar por diminuir o número):

f1(n) = -n + 1

Em seguida, precisamos mapear todos os números inteiros negativos ímpares para números inteiros negativos pares. Precisamos garantir que f2(f1(n)) = -n:

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

Usando os mesmos métodos, encontramos f3e f4:

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

Para combinar essas funções em uma única função, observamos que sempre nque trocamos o sinal ne sempre nque positivo, aumentamos em um e diminuímos em um:

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

Assim, isso pode ser reescrito como:

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

onde odd(n)retorna 1para números ímpares e -1números pares.

Existem 4 soluções no 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_MINpode sempre ser considerado um caso extremo em todas as 4 funções como -INT_MIN == INT_MIN=> f(f(INT_MIN)) = INT_MIN.


É essencialmente o mesmo que a minha resposta do GolfScript (exceto explicado melhor). Isso funciona para 0?
Ben Reich

@BenReich Como indicado na resposta, ele não funciona 0e outros 3 números.
Tyilo

1
@Tylio eu vejo agora. Faz sentido. Parece que você só deve receber o Zbônus se cobrir pelo menos 0.
Ben Reich

@BenReich Removido o bônus até que eu o conserte.
Tyilo

9

Aqui está a minha chance.

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

Exemplo ao vivo :

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

Os tipos de entrada podem ser arbitrariamente adaptados para atender às suas necessidades. Esta versão funciona para literais inteiros menores em magnitude que 2 ^ 32-1.


2
O problema disse que f:Q->Qnão f:Z->Z.
AJMansfield

@AJMansfield seção de pontuação da especificação era para pontos de bônus oferecem para as funções definidas f:Z->Z, pena do texto confuso
ardnew

6
o problema com esta resposta é que parece definir duas funções separadas, enquanto a especificação exige que você defina apenas uma. mas eu não quero começar uma semântica debater, ainda é uma solução muito pensativo
ardnew

@ardnew, oh você está certo. Fui apontado para essa objeção válida apenas alguns segundos antes de compartilhá-la com o Lounge <C ++> no chat SO. Eu me pergunto o que o compilador faz disso (se não incluir as chamadas), mas meu assembly é péssimo.
21413 Rubenvb

1
Eu acho que você pode remover o espaçoreturn -i
Cyoce

6

JavaScript, 18

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

Usando a nova notação de seta gorda (Firefox 22).

Outra versão (18):

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

Versão anterior (20):

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

Exemplo:

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

10
Parece que o JavaScript está evoluindo para o CoffeeScript.
Peter Taylor

4

Mathematica 18

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

Aqui ⌊...⌋está a função de piso. Ele usa apenas números racionais (não listas, números complexos, etc.)

f[10]
f[f[10]]

21/2

-10

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

-9/2

5


3

linguagem de montagem x86 (FASM). O argumento e o resultado estão no registro eax.

Funciona corretamente para -2 ^ 30 <N <+ 2 ^ 30-1

Código executável de 16 bytes.

        use32

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

Nitpicking seus números; 2E30 seria 2 * 10 ^ 30, não 2 ^ 30 como eu acho que você deseja.
Nick T

@NickT Meu erro. Fixo.
#

Tenho certeza de que você deve contar os bytes no código-fonte.
precisa saber é o seguinte

3

Lisp comum: 35 bytes

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

Esquema (e raquete): 36 bytes

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

Ungolfed com comentários e explicação:

(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

Para qualquer número no vai se transformar na fração que é um número exato reais em ambas as línguas.x[1,->]if1/2

A parte de divisão se tornará (/ 1/2 x)então a fração 1/(x*2)que sempre estará abaixo 1. Pois 1será 1/2, 2pois é 1/4, etc.

Para qualquer número abaixo de 1, ifele retornará à fração -1/2, o que faz com que a função faça o (/ -1/2 x)que é, -1/(2*x)mas como podemos esperar que o valor seja o resultado da execução anterior, podemos substituir x por 1 / (x * 2) fazendo uma aplicação dupla-1/((1/(x*2))*2) = -x

Por exemplo, uma vez que se 1transforma na 1/2segunda aplicação, é(/ -1/2 1/2) ==> -1


Como é que isso funciona?
AJMansfield

@AJMansfield adicionou algumas informações. Basta perguntar se há algo incerto. Ler a sintaxe do LISP é como grego, se você ainda não aprendeu e leva algumas semanas para se acostumar.
precisa

3

C, 60 (⌈66 * .9⌉)

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

Aqui está uma versão sem condensação:

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

Esse método funciona usando apenas números inteiros, portanto, ele recebe o bônus de pontuação de 90%. Eu estava originalmente escrevendo em java, mas percebi que esse programa em particular poderia se beneficiar de operadores lógicos no estilo C.

Como não há um número inteiro correspondente a -INT_MIN, f(f(INT_MIN))retorna INT_MIN.

O mapeamento subjacente é algebricamente bastante simples. A execução da instrução x=f(x)substitui x por:

  • x+1, se xé positivo e ímpar
  • -x+1, se xfor positivo e uniforme
  • x-1, se xfor negativo e ímpar
  • -x-1, se xfor negativo e uniforme

O resultado de cada caso cairá no próximo caso na próxima vez que a função for aplicada a x.

Como você pode ver, compor um caso com o caso a seguir produz -x.

O código é o resultado de alguma simplificação inteligente da função para tirar proveito da estrutura de bits dos números inteiros de dois elogios.


3

> <> , 21 + 3 = 24 bytes, 22 pontos

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

Use o intérprete oficial do Python e use a -vopção de linha de comando para inserir entrada, a um custo de 3 bytes.

Tenho a sensação de que isso poderia ser melhor - continuarei olhando para ele e tentarei jogar com calma.

Dada a entrada n, o programa gera

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

onde (n>0)e (n<0)são booleanos. Isso é equivalente à resposta Python da Gelatina

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

mas ><>não tem um operador de exponenciação built-in por isso usamos (1 - 2*(n%2))no lugar de (-1)**n.

A seguir, é apresentada a teoria matemática - leia se (e somente se) você está interessado:

Dada qualquer função f: Z -> Zde tal forma que f(f(n)) = -npara todos nem Z, vemos imediatamente que f(f(f(f(n)))) = n, ou em outras palavras, f^4é a função identidade. Em particular, fé invertível e sua função inversa é f^3. Assim, fé uma permutação de Z, e uma vez que f^4 = Id, segue-se que cada órbita (ou ciclo), da ftem tamanho quer 1, 2, ou 4.

A seguir, vemos isso f(0) = 0. Prova:, f(0) = f(-0) = f(f(f(0))) = -f(0)então f(0) = 0, conforme desejado. Por outro lado, suponha que xesteja em um ciclo de duração 1ou 2mais f(f(x)) = x. Então -x = xsim x = 0.

Assim, fé composto inteiramente de 4 ciclos, exceto pelo ponto fixo (1 ciclo) em 0.

Além disso, todo ciclo de quatro deve ter a forma (x, y, -x, -y)e, girando o ciclo ao redor, podemos assumir isso xe ysomos ambos positivos. Por outro lado, todo produto de 4 ciclos particionando números inteiros diferentes de zero determina uma escolha de f.

Assim, cada escolha de fcorresponde exclusivamente a um gráfico direcionado cujos vértices são números inteiros positivos, de modo que todo vértice é incidente em exatamente uma seta, entrando ou saindo. Mais precisamente, no gráfico não direcionado subjacente, todo vértice tem grau exatamente 1. (Cada 4 ciclos (x y -x -y)com xe ypositivo corresponde à seta x --> y.)

A função desta resposta (e várias outras respostas aqui) corresponde ao gráfico onde 1 --> 2, 3 --> 4e, em geral 2k-1 --> 2k.

Tais gráficos estão em bijeção com infinitas seqüências de pares ordenados (a_n, p_n), onde cada a_num é um número inteiro positivo e cada um p_né um 0ou 1: ou seja, dada uma sequência (a_1, p_1), (a_2, p_2), (a_3, p_3), ..., primeiro emparelhamos 1com 1 + a_1e, em seguida, formamos a flecha 1 --> 1 + a_1ou a flecha 1 + a_1 --> 1dependendo de se p_1é 0ou 1. Essencialmente, a seta é um <sinal ou um >sinal, dependendo da paridade de p_1.

Em seguida, pegue o menor número inteiro positivo não emparelhado ke conte k, exatamente a_2, das etapas, SALTANDO qualquer número que já esteja emparelhado com algo. Emparelhe kcom o resultado e defina a direção da seta, conforme p_2acima. Repita com (a_3, p_3), etc.

Cada flecha será determinada dessa maneira, para que o processo seja bem definido. A função nesta resposta corresponde à sequência (1,0), (1,0), (1,0), ..., uma vez que na etapa no menor inteiro não emparelhado é 2n-1e nenhum número inteiro maior que o 2n-1emparelhado com alguma coisa, então obtemos 2n-1 --> 2npara cada um n(as setas são orientadas dessa maneira porque cada um p_né igual 0).

A cardinalidade desse conjunto é (N*2)^N = N^Nque, no último parágrafo desta resposta2^N , é igual à cardinalidade dos números reais.


As opções de linha de comando são geralmente um byte cada.
Cat

@cat Veja a seção "Invocações especiais" nesta meta post .
Mathmandan # 22/16

2

Para corrigir a resposta J anterior (não tenho reputação suficiente para comentar no original):

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

Apenas substitui o _1&^por 1-~2*2|], que dá o sinal oposto. Então mudei o -para a +(o que importa apenas na entrada de 1e _1).

Aqui estão os testes:

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

Como você pode ver, o domínio e o intervalo são todos de números reais, mas funciona apenas para números inteiros (incluindo 0).

Explicação:

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

2

GolfScript ceiling(26*.9)=24

O Golfscript manipula apenas números inteiros; portanto, aplique o Zbônus para um total de 24 pontos:

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

O caso especial de 0 representa 8 caracteres. Ignorando 0, podemos obter uma resposta de 17 pontos:

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

Este código faz o seguinte em um número inteiro xno topo da pilha:

  • Se xfor 0, deixe 0na pilha e não aplique mais regras.
  • Se xfor par, negue x.
  • Se xfor positivo, adicione 1.
  • Se xfor negativo, subtraia 1.

Isso conecta logicamente conjuntos de 4 números em um ciclo, onde fpercorre elementos do ciclo e os cantos opostos do ciclo são negativos um do outro. Todo número inteiro faz parte de exatamente 1 desses ciclos, exceto 0, que é especial. Por exemplo, para {-8, -7, 7, 8}:

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

Os únicos casos de teste relevantes em que pude pensar foram um ímpar negativo, par negativo, ímpar positivo, par positivo 0e, em seguida, entrei -1e 1já que a proximidade deles 0pode ter causado problemas:

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

Tenho certeza de que o GolfScript real pode ser melhorado um pouco. Não parece que deva ter 26 caracteres! Gostaria de ouvir algumas sugestões.


2

Java, apenas por diversão

Aqui está uma implementação que faz uma bijeção real entre ℤ e ℤ², que é uma função ímpar ao mesmo tempo (g (-x) == -g (x)). Ele trata o elemento ℤ² correspondente como um número complexo e o multiplica por "i" e depois volta a converter em ℤ.

(f (x)) = f (x) =
f (x) = g - (x) = - x

A função é executada em 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 Feliz Ano Novo!


Eu acredito que o espaço em branco é desnecessário.
pppery 26/08

2

Python 3-38

Semelhante à resposta de @ moose, mas f(n) == n,. Funciona para todos os valores inteiros.

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

2

Perl, 33 (sem espaço em branco)

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

Editar:

  • $=.".1"encurtado para "$=.1"(obrigado ardnew).

Matemática:

Matemática

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

Exemplos:

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

solução robusta - os casos de teste de ponto flutuante que você demonstrou não são necessários por especificação (deveriam oferecer pontos de bônus por isso!). Aqui está o seu mesmo algoritmo, com algumas limpezas chegando em 22 caracteres:sub f{yzxzzc?-$_:x.$_}
ardnew

1
@ardnew: Obrigado. Mas eu discordo que sua solução usa o mesmo algoritmo. O algoritmo sub f{yzxzzc?-$_:x.$_}é não estado livre, ele usa um estado através da variável $_. Por esse fmotivo , não é mais uma função (no sentido matemático), porque valores diferentes são possíveis para o mesmo valor de entrada, dependendo do estado (o clima $_contém xou não). Meu algoritmo não usa um estado. As informações são codificadas no valor de saída. Os números inteiros são convertidos em números reais adicionando .1. E os números reais são convertidos novamente em números inteiros com o sinal alternado.
precisa saber é o seguinte

interessante - nenhum dado de estado é usado na sua implementação por causa da atribuição inicial e não por causa de alguma propriedade especial de $=?
ardnew

Eu não sabia que também falhava no meu próprio requisito (que fseria definido Q->Q) com esse xcaractere. também $=.".1"pode ser reduzido para"$=.1"
ardnew

@ardnew: A propriedade especial de $=é apenas que leva apenas números inteiros. O mesmo pode ser conseguido usando uma variável comum: $a=int$_[0]. Mas isso custa três bytes adicionais por causa da função int.
precisa saber é o seguinte

2

Julia, 26

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

Não é super competitivo, mas muito juliano, uma vez que depende de vários envios. Apenas cria um Rational se for um Int, ou um int com um sinal de menos se for qualquer outra coisa. Alguém pode objetar que se trata de 2 funções, mas Julia considera que se trata de uma função com dois métodos, e é equivalente a definir uma função com uma declaração if no tipo de n.


Não é o que um matemático chamaria de função: em Julia 3==3//1retorna, truemas f(3//1)==f(3)retorna false.
Omar

2

Doces , 20 18 bytes

Usa o truque 3 -> 4 -> -3 -> -4 -> 3.

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

Para invocá-lo, use a opção -i no intérprete

Exemplo de invocação dupla:

$ 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 longa:

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 pontos

×-⍨⊢ׯ1*⊢

A fonte tem 9 bytes e se qualifica para o bônus (o que não ajuda em nada). Ele também usa a fórmula da resposta SO principal.




1

Java, 113 bytes

A abordagem é bastante simples. Acabou com mais bytes do que eu imaginava, mas talvez possa ser um pouco mais complicado.

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

Ele basicamente cria 4 "áreas" diferentes de x, utilizando o fato de que Java permite que as variáveis ​​sejam contornadas. Eu tive que fazer uma conversão complicada para números negativos, que é a principal razão pela qual isso acabou sendo maior do que o esperado.

Funciona para todos os x além de -2147483648.


1

Mesma sequência de números (3, 4, -3, -4, 3 ...) que a resposta golfscript, mas implementada em perl (42 caracteres após o espaço em branco ser removido)

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

Mais legível:

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

Ou ainda mais legível:

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

Resultado:

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

O exemplo acima também funciona para não-inteiros: ski @ anito: ~ / mysrc /.../ acme $ echo 1.1234 | perl -e 'sub f {($ _ [0]% 2? 1: -1) * $ _ [0] + ($ _ [0] <0? -1: 1)}; meu $ x = <>; para (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 bytes.

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

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

2
Esta não é uma resposta válida, pois o domínio e o codomain da função não devem ser complexos.
Wrzlprmft

oh, eu sinto muito ... Eu só ler o título e não era tão cuidadosa ... Vamos ver se eu posso editar isso um pouco
bla

1

C ++ - 63 55,8

É assim que o código se parece:

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

Ele não funciona em números inteiros cujo quarto byte é igual a 0xB, pois usa esse valor para acompanhar as passagens. Caso contrário, funciona em qualquer membro de Z, incluindo zero.


você pode explicar isso? na primeira inspeção, parece que você está mantendo um contador de chamadas fcom uma variável estática. mas então qual é o sentido da sqrt?
ardnew

Eu pareço ter entendido mal a pergunta; pensei que uma variável estática estava bem, já que C ++ é uma linguagem orientada a pilha, mas vou corrigir o código. Caso contrário, não faço ideia do porquê de precisar sqrt, pois é arredondado de qualquer maneira com a conversão de tipo. Vou refatorá-lo para que ele funcione sem a variável estática.
precisa saber é o seguinte

Não faço ideia de onde você obteve o 55.8código, mas seu código atual tem 62 bytes. Edit: Não importa, eu não li a pergunta corretamente.
precisa saber é o seguinte

A restrição de que o quarto byte não pode ser igual a 0xB infelizmente torna essa resposta não válida para o desafio, o que exige que ele funcione em (pelo menos) todos os números inteiros.
pppery 26/08

1

Atualizado com a função fornecida pela Synthetica (obviamente quem deve obter crédito por isso agora)

Idioma: Python

Número de caracteres: 41 incluindo espaço em branco

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

Forneça também o nome do idioma que você usou e forneça também a contagem de caracteres.
precisa

Eu gosto de como isso também funciona com não-inteiros. Bem feito. :)
cjfaure

f=lambda x:-float(x) if str(x)==x else`x`é um pouco mais curto: 41 incluindo espaço em branco
ɐɔıɐɔuʎs 25/04

Graças à Synthetica, eu nem sabia sobre o truque dos backticks! : D
HolySquirrel

On inteiros fretorna uma string; a especificação diz que deve retornar um número racional.
Omar

1

Prolog, 36 bytes

Código:

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

Explicado:

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

Exemplo:

10*X.
X = 10.5

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


1

Mouse-2002 , 21 19 12 bytes

$A1%[1%_|1%]

Define uma função A; chame-o como #A,#A,?;;(que esperará o usuário digitar qualquer número). Como alternativa, chame-o como #A,#A,n;;onde nestá qualquer número.


1

Julia, 21

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

Então

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

p // q é a notação literal de julia de números racionais.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.