Como determinar se um número é ímpar ou par sem operações mod - ou - bit a bit? [fechadas]

19

Como determinar se um número é ímpar ou par sem operações mod - ou - bit a bit?

Esse desafio é extremamente ineficiente, mas desafia sua capacidade de pensar fora da caixa em busca de uma solução criativa.

EDIT :

Por favor, crie uma função. Além disso, enquanto regex é uma resposta divertida, a função deve aceitar qualquer número válido.

JUSTIFICATIVA : Esta questão decorre dos meus primeiros dias de programação. O dever de casa para o nosso primeiro dia de aula era escrever um programa simples que imprimisse 'ímpar' ou 'par'. Sendo o pirralho que eu era, não li o livro que tínhamos para a classe, onde ele simplesmente nos mostrava como usá-lo%para determinar isso. Passei meia hora andando de um lado para o outro no meu quarto, tentando pensar em uma maneira de fazer isso e lembrei da palestra que os números podem perder e ganhar precisão à medida que são transmitidos de um tipo primitivo para outro. Portanto, se você pegasse o número, o dividisse por dois e depois o multiplicasse, não seria igual ao número original, saberia que o número era ímpar.

Fiquei surpreso no dia seguinte, enquanto nosso instrutor avaliava nossos programas, que ele achava que era a maneira mais original, embora ineficiente, de solucionar o problema.

Wayne Hartman
fonte
3
Devemos criar uma função ou um programa? Como o IO deve acontecer se tivermos que fazer um programa? Por favor, elabore mais.
Juan
2
Que critério objetivo determinará a resposta aceita? Tamanho do código? Algo mais?
usar o seguinte código
Definitivamente é um número? Deveria dar falsos positivos para uma string?
William
Isso já existe há muito tempo, mas não parece haver qualquer condição vencedora, o que, a meu ver, significa que não há jogo aqui.
dmckee

Respostas:

40

Na maioria das linguagens de programação, a divisão retorna quociente para números inteiros. Então você pode simplesmente verificar isso

(i/2)*2==i
fR0DDY
fonte
6
Não necessariamente a maioria, eu diria. Muitos, talvez.
Joey28 /
11
para garantir que ele seja executado corretamente, você precisa ter certeza de que você joga tudo em um int/ longTipo
Warren
@warren Depende da linguagem de programação / otimizações do compilador / etc. Além disso, você pode usar floor(). Isso funciona perfeitamente em C e C ++.
Mateen Ulhaq
11
0 é um número par?
usuário desconhecido
4
@userunknown: Sim, zero é par.
Keith Thompson
71

Pitão

print('even' if (-1)**n==1 else 'odd')
dan04
fonte
10
A beleza simples / bela simplicidade da matemática ... muito bom!
JSCs
Eu gosto muito deste.
Rob
Lento, mas criativo.
Mateen Ulhaq 1/11/11
21

Brainf *** (179)

Esse é um dos problemas mais interessantes envolvendo lógica condicional que fiz no BF.

+[>,]<--------------------------------------->>+++++[>+++++++
++++++>+++++++++++++++<<-]>++++>++++<<+<+<-[>-<-[>+<-[>-<-[>+<-[>-<-[>
+<-[>-<-[>+<-[>-<[-]]]]]]]]]]>[>>>.<<-<-]>[>.<-]

É preciso uma entrada de texto com um número. Se o número for par, ele gera Ee, se for ímpar, ele gera O.

Estou orgulhoso o suficiente para mostrar uma forma mais legível para humanos:

+[>,]                                                   steps through input until it reaches eof.
<---------------------------------------                gets the numerical value of the last digit
>>+++++[>+++++++++++++>+++++++++++++++<<-]>++++>++++    store E and O
<<+<+<                                                  store a bit indicating parity, and a temporary bit
-[>-<                                                   !1
  -[>+<                                                 && !2
    -[>-<                                               && !3
      -[>+<                                             && !4
        -[>-<                                           && !5
          -[>+<                                         && !6
            -[>-<                                       && !7
              -[>+<                                     && !8
                -[>-<[-]]                               && !9
              ]
            ]
          ]
        ]
      ]
    ]
  ]
]
>[>>>.<<-<-]>[>.<-]                                     Display E or O based on the value of the parity bit.
Peter Olson
fonte
21

Mathematica

SawtoothWave[x / 2] == 0
Exp[I Pi x] - 1 == 0
Sin[5 x / Pi] == 0
Ming-Tang
fonte
2
Você pode dividir essas duas soluções em respostas diferentes?
FUZxxl
Essas quatro soluções não são?
JoeyAbr
Na verdade, todos os nomes incorporados no Mathematica são escritos em maiúscula; portanto, por mais engraçado que pareça, você deve usar Ie em Pivez de ie pi.
David Zhang
15

C

Multiplicado por si só algumas vezes, qualquer número par passará para 0, dado um número inteiro de tamanho finito, e qualquer número ímpar continuará tendo pelo menos o conjunto de bits menos significativo.

#include "stdio.h"
long long input=123;
int main(){
    int a;
    for(a=6;a;a--){
        input*=input;
    }
    if(input){
        printf("Odd");
    }
    else{
        printf("Even");
    }
    return 0;
}

Edit: Como uma função simples:

int isOdd(long long input){
    int a;
    for(a=6;a;a--){
        input*=input;
    }
    return !!input;
}
aaaaaaaaaaaa
fonte
Certifique-se de usar números inteiros não assinados. O excesso de números inteiros assinados é um comportamento indefinido em C; portanto, a otimização pode fazer algo estranho, se desejado.
Joey Adams
13

Python (lento)

n=1234
while n > 1: n -= 2 #slow way of modulus.
print "eovdedn"[n::2]
st0le
fonte
11
Funciona para positivo ... suponho que eu poderia adicionar uma abs()chamada no início.
st0le
@ Josh: Esse truque apareceu aqui algumas vezes já agora :)
Joey
Créditos para gnibblr :)
st0le
@ Joey: Eu não achei que fosse novo, mas o estilo não precisa ser original. :)
JSCs
12

Javascript

/[02468]$/.test(i)

produz truepara um número par. Isso funciona apenas com números inteiros de tamanho razoável (por exemplo, notação não científica quando convertida em uma string e sem uma parte fracionária).

PleaseStand
fonte
2
Para atender ao requisito "função", você pode alterá-lo para simplesmente /[02468]$/.test.
Ry-
Não estava exatamente claro na pergunta, mas seria possível que a entrada não fosse um número /[02468]$/.test('I am a fake even number 0'). Nesse caso, você poderia fazer/^[0-9].[02468]$/.test(i)
William
/-?^\d*[02468]$/seria um pouco mais rigoroso que o seu regex. Você precisaria de mais trabalho para que isso funcione corretamente para números que serão usados ​​usando notação científica.
Thomas Eding
12

Pitão

Como não tenho muita certeza de quais são os critérios de pontuação, aqui estão algumas soluções que eu encontrei por diversão. A maioria deles usa abs(n)para suportar números negativos. A maioria, se não todos, nunca deve ser usada para cálculos reais.

Este é meio chato:

from __future__ import division
def parity(n):
    """An even number is divisible by 2 without remainder."""
    return "Even" if n/2 == int(n/2) else "Odd"

def parity(n):
    """In base-10, an odd number's last digit is one of 1, 3, 5, 7, 9."""
    return "Odd" if str(n)[-1] in ('1', '3', '5', '7', '9') else "Even"

def parity(n):
    """An even number can be expressed as the sum of an integer with itself.

    Grossly, even absurdly inefficient.

    """
    n = abs(n)
    for i in range(n):
        if i + i == n:
            return "Even"
    return "Odd"

def parity(n):
    """An even number can be split into two equal groups."
    g1 = []
    g2 = []
    for i in range(abs(n)):
        g1.append(None) if len(g1) == len(g2) else g2.append(None)
    return "Even" if len(g1) == len(g2) else "Odd"

import ent # Download from: http://wstein.org/ent/ent_py
def parity(n):
    """An even number has 2 as a factor."""
    # This also uses modulo indirectly
    return "Even" if ent.factor(n)[0][0] == 2 else "Odd"

E este é o meu favorito, embora, infelizmente, não funcione (como apontado por March Ho abaixo: só porque todos os números pares são a soma de dois números primos, não significa que todos os números ímpares não sejam).

import itertools
import ent    # Download from: http://wstein.org/ent/ent_py
def parity(n)
    """Assume Goldbach's Conjecture: all even numbers greater than 2 can
    be expressed as the sum of two primes.

    Not guaranteed to be efficient, or even succeed, for large n.

    """
    # A few quick checks
    if n in (-2, 0, 2): return "Even"
    elif n in (-1, 1): return "Odd"
    if n < 0: n = -n    # a bit faster than abs(n)
    # The primes generator uses the Sieve of Eratosthenes
    # and thus modulo, so this is a little bit cheating
    primes_to_n = ent.primes(n)
    # Still one more easy way out
    if primes_to_n[-1] == n: return "Odd"
    # Brutish!
    elif n in (p1+p2 for (p1, p2) in itertools.product(primes_to_n, primes_to_n)):
        return "Even"
    else:
        return "Odd"
jscs
fonte
Soluções fofas :-)
Joey
2
Realmente um necro antigo, mas a resposta da conjectura de Goldbach não imprime Mesmo para 9? Parece um caso de afirmação da consequente falácia #
31 de Março de Ho
Sim, você está absolutamente cem por cento certo, @MarchHo. Ovo na minha cara.
JSCs
10

Haskell

É claro que essa não é a solução criativa e inovadora que você procura, mas quantas vezes vou postar uma resposta Haskell menor que a GolfScript, na verdade? É realmente uma pena que isso não seja um código de golfe.

odd

Mas mais a sério:

data Parity = Even | Odd
            deriving (Show)

parity = p evens odds
  where p (x:xs) (y:ys) i | i == x = Even
                          | i == y = Odd
                          | otherwise = p xs ys i
        evens = interleave [0,2..] [-2,-4..]
        odds = interleave [1,3..] [-1,-3..]
        interleave (x:xs) ys = x : interleave ys xs

fonte
olhares mais longos do que o GolfScript resposta para mim
Warren
2
Eu estava me referindo ao primeiro bloco ( odd), que é uma função interna que retorna True se o número for ímpar. Essa é uma resposta completa por si só e mais curta que a resposta atual do GolfScript (que no momento em que escrevemos isso é 10 caracteres, mas espero que diminua). A questão também é um pouco subespecificada, e é por isso que afirmo que oddé suficiente. Isso pode mudar também.
11
perdeu a primeira resposta na sua resposta :)
Warren
11
No mínimo, o parityalgoritmo funciona em todas as Numinstâncias que são números inteiros. Isso é quente! Embora eu provavelmente tivesse feito evens = [0,2..] >>= \n -> [-n, n]. Semelhante para as probabilidades.
Thomas Eding
7

Usando uma leitura deliberadamente perversa da pergunta, "Como determinar se um número é ímpar ou par", aqui está uma implementação C (assuma boole trueseja definida adequadamente):

bool is_odd_or_even(int n)
{
    return true;
}
Keith Thompson
fonte
A pergunta menciona número, não inteiro. Número como 0.5retornostrue quando não deveria.
21978 Konrad Borowski
6

Ainda não há algoritmos aleatórios ??

C

#include<stdio.h>
#include<stdlib.h>

void prt_parity_of(int n){
  int i,j=2;
  char o[]="eovdedn"
     , f[n=abs(n)]; for(i=n;i-->0;f[i]=1);

  while(j>1){
    while((i=rand()%n)
       == (j=rand()%n)
       || (f[i]&f[j]>0)
       && (f[i]=f[j]=0)
    );for(i=j=0; ++i<n; j+=f[i])
  ;}for(;j<7;j+=2)putchar(o[j]);
}

Emparelha aleatoriamente números no intervalo 0 .. n -1 até menos de 2 serem deixados. É bastante surpreendente ineficiente: O ( n 3 ).


Completamente diferente:

Haskell

import Data.Complex

ft f = (\ω -> sum[ f(t) * exp(0:+2*pi*ω*t) | t<-[-1,-0.9..1] ] )

data Parity = Even | Odd deriving (Show)

parity n
  | all (\(re:+im) -> abs re > abs im) [ft ((:+0).(^^n)) ω | ω<-[0..20]]  = Even
  | otherwise                                                             = Odd

Usa o fato de que a transformação de Fourier de uma função par (por exemplo \x->x^^4) é real, enquanto a transformação de Fourier de uma função ímpar é imaginária.

deixou de girar contra-relógio
fonte
5

Windows PowerShell

function OddOrEven([long]$n) {
  if (0,2,4,6,8 -contains "$n"[-1]-48) {
    "Even"
  } else {
    "Odd"
  }
}
  1. Converter em string
  2. Escolha a última letra (dígito) (essencialmente um mod 10).
  3. Verifique se é 0, 2, 4, 6 ou 8.

Sem operadores bit a bit, sem módulo, conforme solicitado.

Joey
fonte
5

Coq, 103

Fixpoint even n:=match n with O=>true|S n=>odd n end with odd n:=match n with O=>false|S n=>even n end.

Tanto quanto posso dizer, esta é a primeira entrada coq no codegolf.

Ainda mais curto (59):

Fixpoint even n:=match n with O=>true|S n=>negb(even n)end.
ReyCharles
fonte
4

Rubi

n.odd?

Se você deseja imprimir o resultado:

f[n] = ->(n){puts n.odd?? 'odd' : 'even'}
Lowjacker
fonte
Eu sou bastante uso ruby ​​usa mod na .odd?definição.
MrZander
4

Unlambda

O mundo precisa de mais Unlambda.

A Unlambda tem uma vantagem incrível aqui: sua representação padrão ( ahem ) para números são números da Igreja, então tudo o que é necessário é aplicá-los à função binária - e não à função verdadeira. Fácil!

PS: Markdown e Unlambda definitivamente não são feitos um para o outro.

true  = i
false = `ki
not   = ``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki
even? = ``s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki

Verificação para os primeiros números inteiros:

```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki`ki                   => i
```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`kii                     => `ki
```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki``s``s`kski           => i
```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki``s``s`ksk``s``s`kski =>`ki
JB
fonte
3

Golfscript

~,2/),1=\;
VOCÊ
fonte
3

Pitão

print (["even"] + (["odd", "even"] * abs(n)))[abs(n)]

Desempenho semelhante à versão anterior. Trabalha para 0 agora.

Versão anterior incorreta:

print ((["odd", "even"] * abs(n))[:abs(n)])[-1]

Não é particularmente eficiente; tempo e memória, obviamente, O (n): 32 ms para 1.000.000; 2,3 ms para 100000; 3,2 usec para 100. Funciona com números negativos. Lança um erro para 0, porque 0 não é par nem ímpar.

jscs
fonte
3
Zero é definitivamente par. Veja também: en.wikipedia.org/wiki/Parity_of_zero
@jloy: Ah, merda. Eu pensei que era "um recurso, não um bug". Mais revisões ...
jscs
3

Fractran

[65/42,7/13,1/21,17/7,57/85,17/19,7/17,1/3]

aplicado a

63*2^abs(n)

produz 5se né ímpar ou 1se né par.

Atualização : muito mais curta, mas não tão interessante:

[1/4](2^abs(n))

é 2para ímpar ne 1para par n.

Howard
fonte
3

MMIX (4 bytes)

Isso é meio que trapaça. Não uso operações de modificação nem de manipulação de bits. É melhor que o teste de números pares / ímpares seja incorporado. Supondo que $3contenha o número a ser testado e o resultado seja $2:

ZSEV $2,$3,1

define $2como 1se $3é par e 0se não é. O mnemnoric ZSEVsignifica zero-set even e tem a seguinte semântica:

ZSEV a,b,c: if (even b) a = c; else a = 0;

Para a linha acima, mmixalgera esses quatro bytes de montagem:

7F 02 03 01
FUZxxl
fonte
3

Esquema

Esta é a solução mais ineficiente que eu conheço.

(letrec ([even? (lambda (n)
                 (if (zero? n) "even"
                     (odd? (- n 2))))]
         [odd? (lambda (n)
                 (if (= n 1) "odd"
                     (even? (- n 2))))])
  (even? (read)))
Samuel Duclos
fonte
3

Perl

Sobre o quê

use Math::Trig;
print(cos(pi*@ARGV[0])>0?"even":"odd")
ShaiDeshe
fonte
2

JavaScript, 36

function(i){while(i>0)i-=2;return!i}

Retorna truese for par, falsese não for.

Ry-
fonte
2

Perl

$n x '0' =~ /^(00)*$/
Ming-Tang
fonte
2

Pitão

zip((False, True)*(i*i), range(i*i))[-1][0]

testando o quadrado de i, então também funciona com números negativos

mordedor
fonte
2

F #

Recursão mútua pela vitória.

Um número n é par se for zero ou (n-1) for ímpar.

Um número n é ímpar se for diferente de zero e (n-1) for par.

(abs adicionado caso alguém esteja interessado na paridade de números negativos)

let rec even n = n = 0 || odd (abs n - 1) 
    and odd n = n <> 0 && even (abs n - 1)
cfern
fonte
2

Clojure

  (defmacro even?[n]
  `(= 1 ~(concat (list *) (repeat n -1))))
Benjie Holson
fonte
2

O que qualifica como operações bit a bit? Sob o capô, é provável que a divisão inteira por 2 seja implementada como uma mudança de bits.

Supondo que os turnos de bits não estejam disponíveis:

C / C ++

(unsigned char)((unsigned char)(n > 0 ? n : -n) << 7) > 0 ? "odd" : "even"

editar Faltaram alguns parênteses e, finalmente, foram alterados para remover um turno e torná-lo menos. Você pode testar isso com o seguinte (em * nix):

echo 'main(){ std::cout<< (unsigned char)((unsigned char)(n > 0 ? n : -n) << 7) > 0 \
        ? "odd\n" : "even\n";}' \
  | gcc --include iostream -x c++ -o blah -
./blah

... embora no Linux / tcsh, eu tive que escapar da barra invertida \n mesmo que estivesse entre aspas simples. Eu testei em little & big-endian, funciona corretamente em ambos. Além disso, eu copiei isso manualmente; o computador com o qual estou postando não possui um compilador; portanto, pode haver erros.

x86 asm

            mov eax, n          # Get the value
            cmp eax,0           # Is it zero?
            jge pos_label       # If >= 0, skip the next part
            neg eax
pos_label:

.

            imul al, 128

ou

            shl  al, 7

ou

            lea  eax, [eax*8]    # Multiply by 2^3 (left-shift by 3 bits)
            lea  eax, [eax*8]    # ... now it's n*2^6
            lea  eax, [eax*2]    # ... 2^7, or left-shift by 7 bits

... Seguido por:

            cmp al,  0          # Check whether the low byte in the low word is zero or not
            jz  even_label      # If it's zero, then it was an even number
            odd_label           # ... otherwise it wasn't

Como alternativa, o material de troca e comparação também pode ser feito desta maneira:

            sar al,1            # signed integer division by 2 on least-significant byte
            jc  odd_label       # jump if carry flag is set
Brian Vandenberg
fonte
BTW, shle os amigos não são permitidos ...
FUZxxl
2

Em um processador 68000, você pode mover um valor de palavra do endereço definido pelo valor para testar:

 move.l <number to test>,a0
 move.w (a0),d0
 ; it's even if the next instruction is executed

e deixe a interceptação de hardware por erro de endereço determinar a natureza ímpar / par do valor - se a exceção for gerada, o valor será ímpar, se não, o valor será par:

 <set up address error trap handler>
 move.l <pointer to even string>,d1
 move.l <number to test>,a0
 move.w (a0),d0
 <reset address error trap handler>
 <print string at d1>
 <end>

 address_error_trap_handler:
 move.l <pointer to odd string>,d1
 rte

Não funciona em CPUs Intel x86, pois são mais flexíveis no acesso a dados.

Skizz
fonte
2

Pitão

Decidi tentar a solução mais feia e confusa que consegui pensar:

n=input();r=range(n+1)
print [j for i in zip(map(lambda x:str(bool(x))[4],[8&7for i in r]),
map(lambda x:str(x)[1],[[].sort()for x in r])) for j in i][n]

Imprime e se for par, ou se for ímpar.

cortador
fonte
2

Q

Continue subtraindo 2 até x <2 e depois converta para bool

{1b$-[;2]/[2<=;abs x]}
skeevey
fonte