Визуализируйте длинное деление с помощью ASCII art


16

Напишите программу, которая визуализирует длинное деление с помощью ASCII art. Ввод состоит из двух целых чисел, числителя и знаменателя, используя формат ввода по вашему выбору.

Примеры:

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

Правила:

  • Использование оператора деления языка программирования в это разрешено.
  • Использование поддержки больших целых также допускается.
  • Для согласованности:
    • Если частное равно нулю, выведите один ноль в конце трамплина.
    • Если остаток равен нулю, не печатайте его.
    • Не печатайте начальные нули на любых числах.
  • Допускаются лишние переводы строки в конце и завершающие пробелы справа.
  • Решение с наименьшим количеством символов выигрывает.

Ограничения:

  • 0 <= числитель <= 10 72 - 1
  • 1 <= знаменатель <= 9999999

Это означает, что выходные данные никогда не будут шире, чем 80 столбцов.

Тестовый набор и пример реализации:

Вы можете использовать long- Division.c ( gist ) для проверки вашей программы. На самом деле это bash-скрипт с программой на С внутри. Настройте его, чтобы вызвать вашу программу в наборе тестов. Посмотрите на код C внизу, чтобы увидеть справочную реализацию. Пожалуйста, дайте мне знать, если есть какие-либо проблемы с примером программы или набора тестов.

$ ./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!

Редактировать: По запросу я помещаю ввод тестового набора и ожидаемый вывод в текстовые файлы ( gist ). Пример использования (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

Странные команды sed отфильтровывают завершающие символы новой строки и пробелы из вывода программы.


Я обнаружил незначительный недостаток в эталонной реализации, а именно в случае 123000123000123 ÷ 123. Линии вычитания охватывали пустое пространство, но они должны охватывать только длину видимых цифр минуенда. Это исправлено сейчас.
Джои Адамс

2
Я думаю, что результат немного смещен по отношению к англоязычной аудитории гольфа: en.wikipedia.org/wiki/…
hallvabo

Вы можете просто создать файл, который показывает ожидаемый результат всех тестов и ссылку на него?
mellamokb

@mellamokb: Добавлено, спасибо!
Джои Адамс

Как насчет принятия? Вопрос достаточно
взрослый

Ответы:


3

Python 3, 284 257 символов

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

Использование: python3 div.py
ввод: с клавиатуры

test.py

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

выходные матчи ожидается

Версии:
 1. 284
 2. 257 : s,z,f=0,0,0s=z=f=0;z and fz*f; лучше зацикливание; убрал несколько новых строк.


2
вы можете попробовать ideone для python3 и ввода - ideone.com/clone/ZZyzu
ВЫ

3

Haskell, 320 символов

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

Проходит все тесты. Пока этот красивый гольф - я думаю, что здесь еще многое предстоит сделать ...


  • Изменить: (344 -> 339) задержать readвызовы, что уменьшает необходимость вызоваshow , достаточно, чтобы сокращать showкак sне стоит.
  • Редактировать: (339 -> 320) переписал функции форматирования строковых полей

Ухоженная! Я сделал решение на Haskell с 344 символами, но не опубликовал его. Кроме того, я не знал, что вы могли бы использовать символы Unicode для операторов (без -XUnicodeSyntax).
Джои Адамс,

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

Примечание: Как заманчиво , как это выглядит сбрить несколько символов, заменив c=(c==0)?сc=!c? , оно непригодно для использования, поскольку вызывает ошибки, связанные с плавающей запятой.

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

Образец исполнения:

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>");

Редактирование 1 : мелкие исправления ошибок, многочисленные оптимизации кода.

Редактировать 2 : исправить ошибку с 1/7, генерирующую дополнительный вывод.


Тестовый скрипт выявил одну проблему. d(1,7)(и подобные тесты) повторяют знаменатель, а не печатают ничего. Это неправильно, потому что это число должно быть частным числом, умноженным на знаменатель, который равен нулю.
Джои Адамс

Все тесты проходят сейчас.
Джои Адамс

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}

Вызовите с помощью i (делитель, число). Codegolfed JS: http://jsfiddle.net/puckipedia/EP464/ Ungolfed (голландский) JS: http://jsfiddle.net/puckipedia/M82VM/

Возвращает длинное деление (в голландском формате, как я его узнал):

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

Прецедент:

document.write("<pre>"+i(5,25)+"</pre>");
document.write("<pre>"+i(7,65669726752476)+"</pre>");

Эй, это не то же самое, что требуется!
Олег Припин

@BlaXpirit Я знаю, я узнал это таким образом.
puckipedia

Интересный. Хотя, как говорит @BlaXpirit, он не соответствует спецификации. Спецификация предназначена для того, чтобы быть справедливым стандартом сравнения для определения эффективности кода, работающего с кодом, поэтому вы не можете произвольно изменить спецификацию, даже если вы не согласны с форматом вывода :)
mellamokb
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.