Реалізація підрозділу


15

Реалізуйте алгоритм ділення на улюбленій мові, який обробляє ціле ділення. Потрібно обробляти тільки позитивні цифри, але бонусні бали, якщо він також обробляє негативний та змішаний знаки. Результати округляються до дробових результатів.

Програма не може містити /, \, divабо аналогічні оператор. Це повинно бути рутиною, яка не використовує натурні можливості поділу мови.

Вам потрібно обробляти до 32-бітного поділу. Використання повторних віднімань заборонено.

Вхідні дані

Візьміть два входи на stdin, розділені новими лініями або пробілами (на ваш вибір)

740 
2

Вихідні дані

У цьому випадку результат був би 370.

Рішення, яке є найкоротшим, виграє.


буде 740,2також дозволено для входу? тобто розділяються комами?
гніблер

"Результати округляються до дробових результатів" - нормально, тому, мабуть, введення може призвести до нецілого числа ... Але що, як дільник більше, ніж розділений (скажімо, 5 і 10) - це дозволено чи ні?
Aurel Bílý

@gnibber Це було б чудово, але чітко вкажіть це в описі програми.
Томас О

2
використання експонентів та інших математичних функцій дійсно дозволено? вони використовують поділ за лаштунками, тому що багато рішень роблять ab⁻¹
Ming-Tang,

2
це найкоротший час, але я нікого не бачив, коли він
вводить

Відповіді:


27

Пітон - 73 символи

Бере вхід, розділений комами, наприклад 740,2

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

5
Це, мій друг, КЛЮЧ
Аамір

Вихід для "740,2" - 369. Це правильно?
Ельвакс

@Eelvex, треба було <=, виправити його і скоротити :)
gnibbler

14

JavaScript, 61

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

Це робить рядок довжиною дивіденду ,,,,,,(6) і розбивається на дільник ,,,(3), в результаті чого виникає масив довжиною 3:, ['', '', '']довжину якого я потім віднімаю. Однозначно не найшвидший, але, сподіваємось, цікавий все-таки!


2
Моя улюблена реалізація тут поки що. Вітаю за класний код!
Томас Едінг

Я намагався зробити його трохи коротшим. A=Array,P=prompt,P((''+A(+P())).split(','+A(+P())).length)
pimvdb



8

Пітон - 72 символи

Бере вхід, розділений комами, наприклад, 740,2

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

8

Пітона, 37

Крок 1. Перетворити на одинакове.

Крок 2. Алгоритм поділу унарного поділу.

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

7

Пітон - 41 символ

Бере вхід, розділений комами, наприклад 740,2

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

1
Це в деяких випадках гірше, ніж безперервно віднімання. наприклад, вхід 5,4. тоді як цикл буде виконуватися 4 рази, тоді як у випадку віднімання нам доведеться відняти лише один раз.
Аамір

6

Пітона, 70

Щось божевільне, що я просто думав (використовуючи розділений комою вхід):

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

Якщо ви приймаєте невеликі помилки точності поплавця, roundфункцію можна скинути.



3

PHP - 82 символи (баггі)

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

Однак це дуже просте рішення - воно не обробляє дробів або різних знаків (стрибне в нескінченну петлю). Я не буду в цьому деталізувати, це досить просто.

Введення в stdin, розділене новим рядком.

PHP - 141 символ (повно)

$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;

Вхід і вихід такі ж, як і попередній.

Так, це майже вдвічі більше за попередній, але це:

  • правильно поводиться з дробами
  • правильно обробляє знаки
  • ніколи не піде в нескінченний цикл, ПІДНЯТЬСЯ другий параметр 0 - але це ділення на нуль - недійсне введення

Переформатування та пояснення:

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

У цьому операторі ви використовували оператора поділу, ви, можливо, підете з невеликим зрушенням. ;)
Томас О

@Thomas О так ... я помітив це зараз ... я насправді думав про трохи змінити (коли я змінив його на / = 2 замість / = 10) - але це був ще один чар ... Здогадайтесь, я доведеться використовувати його все одно ... До речі, це зовсім не поділ: D.
Aurel Bílý

Питання говорить, що вам потрібно використовувати stdin, для якого PHP має підтримку.
Кевін Браун

@ Bass5098 Aaahhh ... Ну добре, здобув 4 символи ... Виправлено.
Aurel Bílý

3

Рубін 1,9, 28 символів

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

Решта поділу, 21 символ

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

Зразок:

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

Для 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: приватний метод `split 'закликав 69938: Fixnum
rkj

@rkj, Вибачте, тільки Ruby 1.9. Щоб працювати на Ruby 1.8, ви повинні зробити на ('a'*a+'b').split('a'*b).size-13 символи більше.
LBg

3

APL (6)

⌊*-/⍟⎕

/тут не поділ, але foldr. тобто F/a b cє a F (b F c). Якщо я не можу використовувати, foldrоскільки він називається /, це може бути зроблено в 9 символів:

⌊*(⍟⎕)-⍟⎕

Пояснення:

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



2

Haskell, 96 символів

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

Введення в одному рядку.

Код просто шукає відповідь, дістаючи дільник dі помножуючи його на всі цілі числа n >= 0. Нехай mбуде дивіденд. Найбільший nтакий, що n * d <= mобраний для відповіді. Код насправді вибирає найменше nтаке, що n * d > mвіднімає 1 з нього, оскільки я можу взяти перший елемент із такого списку. В іншому випадку мені доведеться взяти останній, але важко працювати, щоб взяти останній елемент із нескінченного списку. Ну, список може бути доведеним як кінцевий, але Haskell не знає кращого при виконанні фільтра, тому він продовжує фільтрувати нескінченно.


2

Звичайний Лісп, 42 символи

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

Приймає простір або розділений рядком вхід


2

Bash, 72 64 символи

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

Виведіть нескінченну кількість нових рядків, візьміть перший x, помістіть їх у файл під назвою f, а потім отримайте розмір f в блоки розміром y. Скористався порадою манатурки, щоб поголити вісім персонажів.


Оскільки “Візьміть два входи на stdin, розділені новими рядками або пробілами (на ваш вибір)”, краще виберіть пізніші, розділені пробілом значення. У такому випадку ви можете написати read x y. Якщо ще кілька пробілів можна зменшити до 64 символів: pastebin.com/Y3SfSXWk
manatwork

1

Пітон - 45 символів

Бере вхід, розділений комами, наприклад, 740,2

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

1

Пітон, 94 символи

Рекурсивний бінарний пошук:

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

Пітона, 148

Інші рішення можуть бути короткими, але вони є масштабними в Інтернеті ?

Ось елегантне рішення постійного часу, що використовує силу CLOUD.

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

Я вже згадував, що він також використовує Haskell?


0

Пітон, 46 байт

Ніхто не розміщував нудне рішення віднімання, тому я не міг протистояти цьому.

a, b = вхід ()
i = 0
тоді як a> = b: a- = b; i + = 1
друк i

0

Smalltalk , Squeak 4.x аромат

визначте це двійкове повідомлення в цілому:

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

Колись гольф, цей коефіцієнт ще довгий (88 символів):

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

Але це розумно швидко:

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

-> 127 мс на моєму скромному mac mini (8 МОп / с)

Порівняно з регулярним поділом:

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

-> 31 мс, це просто в 4 рази повільніше

Я не рахую символів, щоб читати stdin або писати stdout, Squeak не був призначений для сценаріїв.

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

Звичайно, більш дурне повторне віднімання

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

або просто дурне перерахування

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

може також працювати, але насправді не цікаво


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 символів

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

Я визнаю, що це не найшвидше рішення.


0

Пітон 54

Займає введення з комою.

  1. Створює рядок з точок довжиною x
  2. Замінює відрізки точок довжиною y однією комою
  3. Розраховує коми.

Слова, оскільки розмітка вмирає зі списком, а потім кодом ?:

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

Пітона, 37

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

Побудує рядок довжиною x( '0'*x) і використовує розширені нарізки для вибору кожного yсимволу, починаючи з індексуy-1 . Друкує довжину отриманого рядка.

Як і Gnibbler, для цього потрібно ввести розділений комою вхід. Видалення цього коштує 9символів:

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

0

Сітківка 0,7,3, 33 байти (не конкурує)

Мова новітня, ніж виклик. Спершу бере вхід, розділений пробілом, дільником. Ділення на нуль не визначене.

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

Спробуйте в Інтернеті


Як ви рахуєте це як 25 байт? Якщо ви очікуєте нерівномірного введення / виводу, ви повинні так сказати (і я думаю, що це 24 байти). Не знаю, чому ви ставитесь до справи 0 окремо, хоча: retina.tryitonline.net/…
Мартін Ендер

Це було неправильно скопійовано
mbomb007
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.