Visualize divisão longa com arte ASCII

16

Escreva um programa que visualize divisão longa com arte ASCII. A entrada consiste em dois números inteiros, um numerador e um denominador, usando o formato de entrada de sua escolha.

Exemplos:

1234 × 56:

     22
   ----
56|1234
   112
   ---
    114
    112
    ---
      2

1002012 ÷ 12:

     83501
   -------
12|1002012
    96
   ---
     42
     36
     --
      60
      60
      --
        12
        12
        --

0 ÷ 35

   0
   -
35|0

Regras:

  • Uso de operador de divisão da linguagem de programação é permitido.
  • O uso de grande número inteiro de suporte também é permitido.
  • Para consistência:
    • Se o quociente for zero, imprima um único zero no final da prancha de mergulho.
    • Se o restante for zero, não imprima.
    • Não imprima zeros à esquerda em nenhum número.
  • Excesso de novas linhas no final e espaços à direita são permitidos.
  • Solução com o menor número de caracteres ganha.

Limites:

  • 0 <= numerador <= 10 72 - 1
  • 1 <= denominador <= 9999999

Isso implica que a saída nunca será maior que 80 colunas.

Conjunto de teste e implementação de amostra:

Você pode usar long-division.c ( gist ) para testar seu programa. Na verdade, é um script bash com um programa C dentro. Ajuste-o para chamar seu programa no conjunto de testes. Veja o código C na parte inferior para ver a implementação de referência. Informe-me se houver algum problema com o programa de amostra ou o conjunto de testes.

$ ./long-division.c 10 7
   1
  --
7|10
   7
  --
   3
$ ./long-division.c
PASS 1234 ÷ 56
PASS 1002012 ÷ 12
PASS 1 ÷ 1
--- snip ---

Score: 35 / 35
All tests passed!

Edit: Por solicitação, eu coloquei a entrada do conjunto de testes e a saída esperada em arquivos de texto ( essência ). Uso de amostra (bash):

cat input | while read nd; do
    ./program $nd |
        sed 's/\s*$//' | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba'
done > output

diff -u expected output

Os comandos sed estranhos filtram novas linhas e espaços à direita da saída do programa.

Joey Adams
fonte
Descobri uma falha menor na implementação de referência, a saber, no caso de 123000123000123 ÷ 123. As linhas de subtração estavam ocupando espaço em branco, mas deveriam estar apenas no comprimento dos dígitos visíveis do minuendo. Está consertado agora.
Joey Adams
2
Eu acho que a saída é um pouco tendenciosa para o público do golfe que fala inglês: en.wikipedia.org/wiki/…
hallvabo 15/03/11
Você pode apenas criar um arquivo que mostre a saída esperada de todos os testes e vincule-o?
mellamokb
@mellamokb: Adicionado, obrigado!
Joey Adams
Que tal aceitar? A questão é velho o suficiente ...
Oleh Prypin

Respostas:

3

Python 3, 284257 caracteres

div.py

n,t=input().split()
d=int(t)
l=lambda x:len(str(x))
s=l(n)
def p(x):print(' '*(l(d)+s-l(x)+1)+str(x))
p(int(n)//d)
p('-'*s)
p(t+'|'+n)
s=z=f=0
while t:
 try:
  while z<d:z=z*10+int(n[s]);s+=1
 except:t=0
 if z*f:p(z)
 if t:f=1;t=z//d*d;p(t);p('-'*l(z));z-=t

Uso: python3 div.py
Entrada: do teclado

test.py

import sys
sys.stdin=open('input'); sys.stdout=open('output','w')
for line in open('input'): exec(open('div.py').read())

saída corresponde ao esperado

Versões:
 1. 284
 2. 257 : s,z,f=0,0,0s=z=f=0; z and fz*f; melhor loop; removeu algumas novas linhas.

Oleh Prypin
fonte
2
você pode tentar ideone para python3 e de entrada - ideone.com/clone/ZZyzu
VOCÊ
3

Haskell, 320 caracteres

l=length
(®)=replicate
p!v=p&show v
p&s=(p-l s)®' '++s
0§_=[];_§l=l
d[m,n]=l c!(read m`div`e):l c&(l m®'-'):c:drop 1(g 0(map(toInteger.fromEnum)m)$1+l n)where
 e=read n;c=n++'|':m
 g r(d:z)p=i§[o!k,o!(i*e),o&(l(show k)®'-')]++g j z o where k=r*10+d-48;(i,j)=k`divMod`e;o=1+p
 g r[]p=r§[p!r]
main=interact$unlines.d.words

Passa em todos os testes. Enquanto isso é bonito - acho que ainda há mais a ser feito aqui ...


  • Editar: (344 -> 339) atrasa as readchamadas, o que reduz a necessidade de chamadasshow , o suficiente para abreviar showcomo snão vale a pena.
  • Edit: (339 -> 320) reescreveu funções de formatação de campos de string
MtnViewMark
fonte
Arrumado! Eu fiz uma solução Haskell com 344 caracteres, mas não a publiquei. Além disso, eu não sabia que você poderia usar símbolos Unicode para operadores (sem -XUnicodeSyntax).
Joey Adams
3

JavaScript (400 394 418 )

function d(n,d){t=parseInt;p=function(v){return(s+v).substring(v.length)};a=function(v,c){return v.replace(/\d/g,c)};w='\n';q=b=o=c=e='';s=a(d,' ')+' ';f=true;i=-1;z='0';while(++i<n.length){s+=' ';if(t(c+=n[i])>=t(d)){q+=r=Math.floor(t(c)/t(d));o+=(!f?p(c)+w:e)+p(''+r*t(d))+w+p(a(c,'-'))+w;c=t(c)%t(d);f=false}else if(!f){q+=z;}c=(c==0)?e:e+c}return p(!q?z:q)+w+p(a(n,'-'))+w+d+'|'+n+w+o+(q?p(c):e)}

OBSERVAÇÃO: Por mais tentador que pareça eliminar alguns caracteres substituindo c=(c==0)?por c=!c?, não é utilizável porque causa bugs relacionados a pontos flutuantes.

http://jsfiddle.net/nLzYW/9/

Execução de amostra:

document.writeln("<pre>");
document.writeln(d("1234","56"));
document.writeln();
document.writeln(d("1002012","12"));
document.writeln();
document.writeln(d("0","35"));
document.writeln();
document.writeln(d("123000123000123","123"));
document.writeln("</pre>");

Edit 1 : Pequenas correções de bugs, inúmeras otimizações de código.

Editar 2 : Corrija o erro com 1/7 gerando saída extra.

mellamokb
fonte
O script de teste revelou um problema. d(1,7)(e testes similares) repetem o denominador em vez de imprimir nada. Isso está errado porque esse número deve ser o dígito quociente vezes o denominador, que é zero.
Joey Adams
Todos os testes passam agora.
Joey Adams
1

Javascript: (372)

function g(a){for(var c="",e=0;e<a;e++)c=" "+c;return c}function i(a,c){for(var e=a+"/"+c+"\\",j=(""+c).split(""),k="",d=0,b=0;b<j.length;b++){d*=10;d+=parseInt(j[b],10);var f=d>9?b-1:b,h=0;h=Math.floor(d/a);d%=a;f=g(f+a.toString().split("").length);f+=h*a+"\n"+g(b+a.toString().split("").length)+"--\n"+g(b+a.toString().split("").length)+d+"\n";k+=f;e+=h}return e+"\n"+k}

Invoque usando i (divisor, número). JS codegolfed: http://jsfiddle.net/puckipedia/EP464/ Ungolfed (holandês) JS: http://jsfiddle.net/puckipedia/M82VM/

Retorna a divisão longa (no formato holandês, como eu aprendi):

5/25\05
 0
 --
 2
 25
  --
  0

Caso de teste:

document.write("<pre>"+i(5,25)+"</pre>");
document.write("<pre>"+i(7,65669726752476)+"</pre>");
puckipedia
fonte
Ei, isso não é o mesmo que necessário!
Oleh Prypin
@BlaXpirit Eu sei, eu aprendi dessa maneira.
Puckipedia
Interessante. Embora como @BlaXpirit diz, ele não segue as especificações. A especificação é destinado a ser um nível de comparação para determinar a eficiência do código golfed-código, para que você não pode arbitrariamente alterar a especificação, mesmo se você não concordar com o formato de saída :)
mellamokb