Divisão de implementos


15

Implemente um algoritmo de divisão no seu idioma favorito que lida com a divisão inteira. Ele precisa apenas lidar com números positivos - mas pontos de bônus se ele também lidar com a divisão de sinais negativos e mistos. Os resultados são arredondados para resultados fracionários.

O programa não pode conter os /, \, divou semelhantes operadores. Deve ser uma rotina que não use os recursos de divisão nativos do idioma.

Você só precisa lidar com a divisão de até 32 bits. O uso de subtração repetida não é permitido.

Entrada

Tome duas entradas no stdin separadas por novas linhas ou espaços (sua escolha)

740 
2

Resultado

Nesse caso, a saída seria 370.

A solução que é o menor ganha.


740,2também é permitido para a entrada? ou seja, vírgula separada?
Gnibbler

"Os resultados são arredondados para resultados fracionários" - ok, portanto, aparentemente, a entrada também pode resultar em um número não inteiro ... Mas e quanto ao divisor ser maior que o dividido (por exemplo, 5 e 10) - isso é permitido ou não?
Aurel Bílý

@gnibber Isso seria bom, mas deixe claro na descrição do programa.
Thomas O

2
o uso de exponenciais e outras funções matemáticas é realmente permitido? eles usam divisão nos bastidores, porque muitas soluções estão fazendo ab⁻¹
Ming-Tang

2
este é mais curto de tempo, mas eu não vi vez que alguém o código
phuclv

Respostas:


27

Python - 73 caracteres

Toma entrada separada por vírgula, por exemplo 740,2

from math import*
x,y=input()
z=int(exp(log(x)-log(y)))
print(z*y+y<=x)+z

5
Este, meu amigo, é CLEVER
Aamir

A saída para "740,2" é 369. Isso está correto?
Eelvex 17/02/11

@Eelvex, deveria ter sido <=, fixa-lo e tornou mais curto :)
gnibbler

14

JavaScript, 61

A=Array,P=prompt,P((','+A(+P())).split(','+A(+P())).length-1)

Isso torna uma string o comprimento do dividendo ,,,,,,(6) e se divide no divisor ,,,(3), resultando em uma matriz de comprimento 3 ['', '', '']:, cujo comprimento então eu subtraí um. Definitivamente não é o mais rápido, mas espero que seja interessante!


2
Minha implementação favorita aqui até agora. Parabéns pelo código legal!
Thomas Eding

Eu tentei torná-lo um pouco mais curto. A=Array,P=prompt,P((''+A(+P())).split(','+A(+P())).length)
Pimvdb

10

JavaScript - 36 caracteres

p=prompt;alert(p()*Math.pow(p(),-1))

5
Substituir alertpor pfornecerá alguns caracteres extras. :)
Casey Chu

9

Mathematica: 34 caracteres

Resolve simbolicamente a equação (xa == b)

Solve[x#[[1]]==#[[2]],x]&@Input[]

2
23 chars,Solve[x#==#2]&@@Input[]
chyanog

8

Python - 72 caracteres

Toma entrada separada por vírgula, por exemplo, 740,2

x,y=input();z=0
for i in range(32)[::-1]:z+=(1<<i)*(y<<i<=x-z*y)
print z

8

Python, 37

Etapa 1. Converta para unário.

Etapa 2. Algoritmo de divisão unário.

print('1'*input()).count('1'*input())

7

Python - 41 chars

Takes comma separated input, eg 740,2

x,y=input();z=x
while y*z>x:z-=1 
print z

1
This, in some cases, is worse than continuously subtracting. e.g., input is 5,4. while loop will run 4 times while in case of subtraction, we will only have to subtract once.
Aamir

6

Python, 70

Something crazy I just thought (using comma separated input):

from cmath import*
x,y=input()
print round(tan(polar(y+x*1j)[1]).real)

If you accept small float precision errors, the round function can be dropped.



3

PHP - 82 caracteres (buggy)

$i=fgets(STDIN);$j=fgets(STDIN);$k=1;while(($a=$j*$k)<$i)$k++;echo($a>$i?--$k:$k);

Esta é uma solução muito simples, no entanto - ela não lida com frações ou sinais diferentes (poderia entrar em um loop infinito). Não vou entrar em detalhes neste, é bastante simples.

A entrada está em stdin, separada por uma nova linha.

PHP - 141 caracteres (completo)

$i*=$r=($i=fgets(STDIN))<0?-1:1;$j*=$s=($j=fgets(STDIN))<0?-1:1;$k=0;$l=1;while(($a=$j*$k)!=$i){if($a>$i)$k-=($l>>=2)*2;$k+=$l;}echo$k*$r*$s;

Entrada e saída iguais à anterior.

Sim, isso é quase o dobro do tamanho do anterior, mas:

  • lida com frações corretamente
  • lida com sinais corretamente
  • nunca entrará em um loop infinito, a menos que o segundo parâmetro seja 0 - mas isso é divisão por zero - entrada inválida

Re-formatar e explicação:

$i *= $r = ($i = fgets(STDIN)) < 0 ? -1 : 1;
$j *= $s = ($j = fgets(STDIN)) < 0 ? -1 : 1;
                                    // First, in the parentheses, $i is set to
                                    // GET variable i, then $r is set to -1 or
                                    // 1, depending whether $i is negative or
                                    // not - finally, $i multiplied by $r ef-
                                    // fectively resulting in $i being the ab-
                                    // solute value of itself, but keeping the
                                    // sign in $r.
                                    // The same is then done to $j, the sign
                                    // is kept in $s.

$k = 0;                             // $k will be the result in the end.

$l = 1;                             // $l is used in the loop - it is added to
                                    // $k as long as $j*$k (the divisor times
                                    // the result so far) is less than $i (the
                                    // divided number).

while(($a = $j * $k) != $i){        // Main loop - it is executed until $j*$k
                                    // equals $i - that is, until a result is
                                    // found. Because a/b=c, c*b=a.
                                    // At the same time, $a is set to $j*$k,
                                    // to conserve space and time.

    if($a > $i)                     // If $a is greater than $i, last step
        $k -= ($l >>= 2) * 2;       // (add $l) is undone by subtracting $l
                                    // from $k, and then dividing $l by two
                                    // (by a bitwise right shift by 1) for
                                    // handling fractional results.
                                    // It might seem that using ($l>>=2)*2 here
                                    // is unnecessary - but by compressing the
                                    // two commands ($k-=$l and $l>>=2) into 1
                                    // means that curly braces are not needed:
                                    //
                                    // if($a>$i)$k-=($l>>=2)*2;
                                    //
                                    // vs.
                                    //
                                    // if($a>$i){$k-=$l;$l>>=2;}

    $k += $l;                       // Finally, $k is incremented by $l and
                                    // the while loop loops again.
}

echo $k * $r * $s;                  // To get the correct result, $k has to be
                                    // multiplied by $r and $s, keeping signs
                                    // that were removed in the beginning.

Você usou um operador de divisão neste, mas pode se dar bem com uma pequena mudança. ;)
Thomas O

@ Thomas O sim ... eu notei isso agora ... Na verdade, eu estava pensando em mudar um pouco (quando mudei para / = 2 em vez de / = 10) - mas era mais um caractere ... Acho que eu ' terei que usá-lo de qualquer maneira ... Mas isso não é divisão: D.
Aurel Bílý

A pergunta diz que você precisa usar stdin, que o PHP tem suporte.
27611 Kevin Kevin Brown

@ Bass5098 Aaahhh ... Oh, bem, ganhou 4 caracteres ... Fixo.
Aurel Bílý

3

Ruby 1.9, 28 caracteres

(?a*a+?b).split(?a*b).size-1

Resto da divisão, 21 caracteres

?a*a=~/(#{?a*b})\1*$/  

Amostra:

a = 756
b = 20
print (?a*a+?b).split(?a*b).size-1  # => 37
print ?a*a=~/(#{?a*b})\1*$/         # => 16

Para Ruby 1.8:

a = 756
b = 20
print ('a'*a+'b').split('a'*b).size-1  # => 37
print 'a'*a=~/(#{'a'*b})\1*$/          # => 16

NoMethodError: private method `split' called for 69938:Fixnum
rkj

@rkj, Sorry, Ruby 1.9 only. To run on Ruby 1.8 you must do ('a'*a+'b').split('a'*b).size-1, 3 characters bigger.
LBg

3

APL (6)

⌊*-/⍟⎕

/ is not division here, but foldr. i.e, F/a b c is a F (b F c). If I can't use foldr because it's called /, it can be done in 9 characters:

⌊*(⍟⎕)-⍟⎕

Explanation:

  • : input()
  • ⍟⎕: map(log, input())
  • -/⍟⎕: foldr1(sub, map(log, input()))
  • *-/⍟⎕: exp(foldr1(sub, map(log, input())))
  • ⌊*-/⍟⎕: floor(exp(foldr1(sub, map(log, input()))))


2

Scala 77

def d(a:Int,b:Int,c:Int=0):Int=if(b<=a)d(a-b,b,c+1)else c
d(readInt,readInt)

2

Haskell, 96 characters

main=getLine>>=print.d.map read.words
d[x,y]=pred.snd.head.filter((>x).fst)$map(\n->(n*y,n))[0..]

Input is on a single line.

The code just searches for the answer by taking the divisor d and multiplying it against all integers n >= 0. Let m be the dividend. The largest n such that n * d <= m is picked to be the answer. The code actually picks the least n such that n * d > m and subtracts 1 from it because I can take the first element from such a list. In the other case, I would have to take the last, but it's hard work to take the last element from an infinite list. Well, the list can be proven to be finite, but Haskell does not know better when performing the filter, so it continues to filter indefinitately.


2

Common Lisp, 42 charaacters

(1-(loop as x to(read)by(read)counting t))

Accepts space or line-separated input


2

Bash, 72 64 characters

read x y;yes ''|head -n$x>f;ls -l --block-size=$y f|cut -d\  -f5

Output an infinite number of newlines, take the first x, put them all into a file called f, then get the size of f in blocks the size of y. Took manatwork's advice to shave off eight characters.


As “Take two inputs on stdin separated by new lines or spaces (your choice)”, better choose the later, the space separated values. In which case you can write read x y. With a few more spaces removed can be reduced to 64 characters: pastebin.com/Y3SfSXWk
manatwork

1

Python - 45 chars

Takes comma separated input, eg 740,2

x,y=input()
print-1+len((x*'.').split('.'*y))

1

Python, 94 characters

A recursive binary search:

a,b=input()
def r(m,n):return r(m,m+n>>1)if n*b>a else n if n*b+b>a else r(n,2*n)
print r(0,1)

1

Python, 148

Other solutions may be short, but are they web scale?

Here's an elegant, constant-time solution that leverages the power of the CLOUD.

from urllib import*
print eval(urlopen('http://tryhaskell.org/haskell.json?method=eval&expr=div%20'+raw_input()+'%20'+raw_input()).read())['result']

Did I mention it also uses Haskell?


0

Python, 46 bytes

Ninguém postou a solução de subtração entediante, então não pude resistir a fazê-lo.

a, b = entrada ()
i = 0
enquanto a> = b: a- = b; i + = 1
imprimir i

0

Smalltalk , sabor Squeak 4.x

defina esta mensagem binária em Inteiro:

% d 
    | i |
    d <= self or: [^0].
    i := self highBit - d highBit.
    d << i <= self or: [i := i - 1].
    ^1 << i + (self - (d << i) % d)

Depois de jogar golfe, esse quociente ainda é longo (88 caracteres):

%d|i n|d<=(n:=self)or:[^0].i:=n highBit-d highBit.d<<i<=n or:[i:=i-1].^1<<i+(n-(d<<i)%d)

Mas é razoavelmente rápido:

[0 to: 1000 do: [:n |
    1 to: 1000 do: [:d |
        self assert: (n//d) = (n%d)]].
] timeToRun.

-> 127 ms no meu modesto mac mini (8 MOp / s)

Comparado à divisão regular:

[0 to: 1000 do: [:n |
    1 to: 1000 do: [:d |
        self assert: (n//d) = (n//d)]].
] timeToRun.

-> 31 ms, é apenas 4 vezes mais lento

Não conto os caracteres para ler stdin ou escrever stdout, o Squeak não foi projetado para scripts.

FileStream stdout nextPutAll:
    FileStream stdin nextLine asNumber%FileStream stdin nextLine asNumber;
    cr

Claro, subtração repetida mais estúpida

%d self>d and:[^0].^self-d%d+1

ou enumeração estúpida

%d^(0to:self)findLast:[:q|q*d<=self]

poderia funcionar também, mas não é realmente interessante


0
#include <stdio.h>
#include <string.h>
#include <math.h>


main()
{
   int i,j,ans;
   i=740;
   j=2;

   ans = pow(10,log10(i) - log10(j));
   printf("\nThe answer is %d",ans);
}

0

DC: 26 caracteres

?so?se0[1+dle*lo>i]dsix1-p

Admito que não é a solução mais rápida.


0

Python 54

Recebe entrada delimitada por vírgula.

  1. Cria uma sequência de pontos de comprimento x
  2. Substitui segmentos de pontos de comprimento y por uma única vírgula
  3. Conta vírgulas.

Palavras porque a remarcação morre com uma lista seguida por código ?:

x,y=input()
print("."*x).replace("."*y,',').count(',')

0

Q, 46

{-1+(#){x-y}[;y]\[{s[x-y]<>(s:signum)x}[y];x]}

.

q){-1+(#){x-y}[;y]\[{s[x-y]<>(s:signum)x}[y];x]}[740;2]
370
q){-1+(#){x-y}[;y]\[{s[x-y]<>(s:signum)x}[y];x]}[740;3]
246


0

Python, 40 caracteres

print(float(input())*float(input())**-1)

0

Python, 37

x,y=input()
print len(('0'*x)[y-1::y])

Constrói uma sequência de length x( '0'*x) e usa fatias estendidas para escolher todos osy caracteres, começando no índicey-1 . Imprime o comprimento da sequência resultante.

Como o Gnibbler, isso exige entrada separada por vírgula. Removê-lo custa 9caracteres:

i=input
x,y=i(),i()
print len(('0'*x)[y-1::y])

0

Retina 0.7.3, 33 bytes (não competindo)

A linguagem é mais nova que o desafio. Recebe a entrada separada por espaço com o divisor primeiro. A divisão por zero é indefinida.

\d+
$*
^(.+) (\1)+.*$
$#+
.+ .*
0

Experimente online


Como você conta isso como 25 bytes? Se você espera E / S unárias, deve dizer isso (e acho que são 24 bytes). Mas não sei por que você trata o caso 0 separadamente: retina.tryitonline.net/…
Martin Ender

Foi copiado
incorretamente #
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.