Легко перемножувати числа


34

Ваше завдання - визначити, чи легко два числа перемножити . Це означає, що їхнє множення на основі 10-ти не має жодного перенесення (перегрупування) між значеннями місця, дивлячись як на етапи множення, так і на етап додавання. Це відбувається, коли кожна пара чисел, що множиться, дає 9 або менше, а сума кожного стовпця дорівнює 9 або менше.

Наприклад, 331і 1021їх легко розмножувати:

   331
x 1021
------
+  331
  662
   0
331
------
337951

І те саме відбувається (як завжди), якщо ми множимо в іншому порядку:

  1021
x  331
------
+ 1021
 3063
3063
------
337951

Але, 431і 1021їх не просто розмножувати, коли між стовпцями зазначено перенесення:

   431
x 1021
------
+  431
  862
   0
431
------
440051
 ^^^

Крім того, 12і 16їх непросто розмножувати, тому що перенесення відбувається при множенні, 12 * 6щоб отримати 72, хоча жодне перенесення не відбувається на етапі додавання.

  12
x 16
----
+ 72
 12
----
 192

Вхідні дані: Дві додатні цілі числа або їх рядкові подання. Ви можете припустити, що вони не переповнять цілий тип вашої мови, а також їхній продукт.

Вихід: одне послідовне значення, якщо їх легко помножити, і інше послідовне значення, якщо ні.

Тестові приклади: перші 5 легко розмножувати, останні 5 - ні.

331 1021
1021 331
101 99
333 11111
243 201

431 1021
12 16
3 4
3333 1111
310 13

[(331, 1021), (1021, 331), (101, 99), (333, 11111), (243, 201)]
[(431, 1021), (12, 16), (3, 4), (3333, 1111), (310, 13)]

Табло:


1
Чи може вхід для кожного числа бути переліком цифр?
dylnan

@dylnan Ні, хоча список символів за замовчуванням дійсний для рядкового параметра.
xnor

Відповіді:


14

Желе , 7 байт

Dæc/>9Ẹ

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

Використовує згортку (яку я сприяв Jelly: D)

Як це працює

Dæc/>9Ẹ
D        converts to decimal list
 æc      convolution
    >9Ẹ  checks if any number is greater than 9

o wow convolution: DI думаю, що це вперше я бачу згортання, яке використовується в гольф-коді: D +1
HyperNeutrino



@LuisMendo Ні, це інша згортання.
Ерік Атголфер

BTW Останні 3 байти можна замінити <⁵Ạдля виведення без булевого НЕ, виконаного на ньому.
Ерік Атголфер

8

JavaScript (ES6), 67 байт

Вводиться як 2 рядки в синтаксисі currying (a)(b). Повертається falseлегко чи trueне просто.

a=>b=>[...a].some((x,i,a)=>[...b].some(y=>(a[-++i]=~~a[-i]+x*y)>9))

Тестові справи


Alt версія (несправна), 64 55 52 байти

Збережено 3 байти, взявши рядки, як це запропонував @Shaggy
Як вказував @LeakyNun, цей метод не зможе отримати деякі великі цілі числа

Вводиться як 2 рядки в синтаксисі currying (a)(b). Повертається trueлегко чи falseне просто.

a=>b=>/^.(0.)*$/.test((g=n=>[...n].join`0`)(a)*g(b))

Тестові справи

Як?

Ідея тут полягає в тому, щоб явно розкрити носії, вставляючи нулі перед кожною цифрою кожного фактора.

Приклади:

  • 331 x 1021 стає 30301 x 1000201 , що дає 30307090501 замість 337951 . Додавши до результату початковий нуль і згрупувавши всі цифри по 2, це можна записати як 03 03 07 09 05 01 . Усі групи менше 10 , це означає, що в стандартному множенні не було б жодного перенесення.

  • 431 x 1021 стає 40301 x 1000201 , що дає 40309100501 і може бути записано як 04 03 09 10 05 01 . Цього разу у нас є 10, яке виявляє перенесення у стандартному множенні.


Може ... Чи можемо ми мати базове пояснення щодо алгоритму?
повністюлюдсько

@totallyhuman Я додав пояснення. (На жаль ... і також виправлено помилку.)
Арнольд

1
Схоже, ви повинні бути в змозі зберегти 3 байти, взявши вхідні дані як рядки.
Кудлатий

3
Мені знадобилося ціла вічність, щоб знайти (теоретичний) зустрічний приклад, який ваш алгоритм вийде з ладу: tio.run/##y0rNyan8/9/l8LJk/f///… ( 108в середині переплутав ваш алгоритм)
Leaky Nun

@LeakyNun Приємна знахідка. Так, він теоретично може переповнювати.
Арнольд

6

Аліса , 30 байт

/Q.\d3-&+k!*?-n/ o @
\ic/*2&w~

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

Виходи 1 легкі та 0важкі.

Числа легко перемножувати тоді і лише тоді, коли цифра суми добутку дорівнює добутку цифри.

/i    Input both numbers as a single string
.     Duplicate this string
/*    Coerce into two integers and multiply
2&w   Push return address twice (do the following three times)
~\Q     Swap the top two stack entries, then reverse the stack
        This produces a 3-cycle, and the first iteration coerces
        the original input string into two integers
c       Convert into individual characters
\d3-&+  Add all numbers on the stack except the bottom two (i.e., add all digits)
k     Return to pushed address (end loop)
      At this point, all three numbers are replaced by their digit sums
!*?   Multiply the digit sums of the original two numbers
-     Subtract the digit sum of the product
n     Logical negate: convert to 1 or 0
/o@   Output as character and terminate

4

MATL , 10 байт

,j!U]Y+9>a

Виходи 0легкі, 1важкі.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

,       % Do twice
  j     %   Input as a string
  !     %   Transpose into a column vector of characters
  U     %   Convert each character to number. Gives a numeric column vector
]       % End
Y+      % Convolution, full size
9>      % Greatear than 1? Element-wise
a       % Any: true if there is some true entry. Implicitly display

4

R , 135 110 109 86 байт

function(m,n)any(convolve(m%/%10^(nchar(m):1-1)%%10,n%/%10^(1:nchar(n)-1)%%10,,"o")>9)

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

Приймає введення як рядки.

Це некрасиво, але це працює ™.

Тепер для цього використовується підхід згортання, як у відповіді Leaky Nun , тому він приймає введення як цілі числа, і повертається TRUEдля важкого перемноження чисел іFALSE для легкого множення.

У мене завжди були проблеми з перенесенням підходів до згортання, але сьогодні я нарешті прочитав документацію :

Зауважимо, що звичайне визначення згортки двох послідовностей xі yзадаєтьсяconvolve(x, rev(y), type = "o")

Що просто нерозумно. Таким чином, видобуток цифр змінюється на зворотному рівні n, і він перетворюється на порт відповіді Лікі Нун.


4

Python 2 , 88 байт

lambda n,m:any(sum(n/10**(k-j)%10*(m/10**j%10)for j in range(k+1))>9for k in range(n+m))

Приймає два цілі числа як вхідні дані та повертає False(їх легко множити) або True(ні).

Спробуйте в Інтернеті! (занадто повільно для одного з тестових випадків)



len(`n+m`)насправді не вдасться 40, 30 .
Денніс

len(`n+m`)+1?
Leaky Nun

Це не вдається для 400, 300 . len(`n`+`m`)повинен зробити, хоча.
Денніс

4

JavaScript (Node.js) , 43 41 37 36 байт

Дякуємо @ Деннісу за ідею використовувати строкову інтерполяцію у цій відповіді та зберегти 4 байти!

Дякую @ ØrjanJohansen за -1!

a=>b=>eval(`0x${a}*0x${b}<0x${a*b}`)

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

Звичайно, коли база призначення менша, ніж початкова база (як, наприклад, у моїй відповіді на Jelly, база 2), <необхідно перевернути.


Вітаю, що першим зрозумів, що використовує конверсію бази, за що я дарую вам щедрості!
xnor

3

Мова Вольфрама (Mathematica) , 75 66 65 56 байт

f:=#~FromDigits~x&
g:=Max@CoefficientList[f@#2f@#,x]<=9&

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

Отримання 2 рядкових входів

Пояснення:

f:=#~FromDigits~x&                      (* Turns the number to a polynomial
                                           with the digits as coefficients      *)
g:=Max@CoefficientList[f@#2f@#,x]<=9&   (* Polynomial multiplication, and check
                                           whether all coefficients are smaller
                                           than 10                              *)

-9 для зміни використання рядка в якості введення

-1 для використання оператора infix

-9 Дякую @MartinEnder за Maxфункцію


3

Пітон 2 , 158 135 123 113 байт

-12 байт завдяки Leaky Nun -10 байт завдяки ovs

a,b=input()
e=enumerate
l=[0,0]*len(a+b)
for i,x in e(a):
 for j,y in e(b):l[i-~j]+=int(x)*int(y)
print max(l)<10

Спробуйте в Інтернеті! або Спробуйте всі тестові приклади


Не all(d[k]<10for k in d)працює чи це просто Python 3?
shooqie

1
@shooqie так, це так, але зараз це список c:
Стержень


3

Юлія 0,6 , 30 байт

~x=any(conv(digits.(x)...).>9)

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

Введення - кордон чисел, вихід - true для важко перемножуваних чисел і falseдля простих.

. це елементне функціональне застосування.

...розширює кортеж (списків цілих цифр) на два окремі входи convфункції.



3

SNOBOL4 (CSNOBOL4) , 268 264 247 246 243 131 байт

	DEFINE('D(A)')
	M =INPUT
	N =INPUT
	OUTPUT =EQ(D(M) * D(N),D(M * N)) 1	:(END)
D	A LEN(1) . X REM . A	:F(RETURN)
	D =D + X	:(D)
END

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

Портує підхід Нітродоном . Я думаю, що це перший раз, коли я коли-небудь визначав функцію в SNOBOL Dдля цифрної суми.

	DEFINE('D(A)')					;* function definition
	M =INPUT					;* read input
	N =INPUT					;* read input
	OUTPUT =EQ(D(M) * D(N),D(M * N)) 1	:(END)	;* if D(M)*D(N)==D(M*N),
							;* print 1 else print nothing. Goto End
D	A LEN(1) . X REM . A	:F(RETURN)		;* function body
	D =D + X	:(D)				;* add X to D
END

стара версія, 243 байти:

	M =INPUT
	N =INPUT
	P =SIZE(M)
	Q =SIZE(N)
	G =ARRAY(P + Q)
Z	OUTPUT =LE(P)	:S(E)
	M LEN(P) LEN(1) . A
	J =Q
Y	GT(J)	:F(D)
	N LEN(J) LEN(1) . B
	W =I + J
	X =G<W> + A * B
	G<W> =LE(A * B,9) LE(X,9) X	:F(E)
	J =J - 1	:(Y)
D	P =P - 1	:(Z)
E
END

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

Введення на STDIN, розділене новими рядками, вихід у STDOUT: єдиний новий рядок, який легко перемножувати, і жоден вихід для нелегкого множення.

Це не виграє жодної нагороди, але це інший підхід (ну, справді це наївний підхід). Я не думаю, що я міг би написати це в кубікс, але SNOBOL досить жорсткий, щоб працювати з ним, як є.

Оскільки він приймає введення як рядок, це буде працювати для будь-якого вводу з меншим числом 512 цифр; Я не на 100% впевнений, наскільки великийARRAY можуть бути SNOBOL.

INPUT буферизований у цій версії SNOBOL, щоб мати максимальну ширину 1024 символів; всі інші символи потім втрачаються. Здається, що АРІЙ може бути досить великим; набагато більше 2048 клітин, необхідних.

	M =INPUT				;*read input
	N =INPUT				;*read input
	P =SIZE(M)				;*P = number of M's digits, also iteration counter for outer loop
	Q =SIZE(N)				;*Q = number of N's digits
	G =ARRAY(P + Q)				;*G is an empty array of length P + Q
Z	GE(P)	:F(T)				;*if P<0, goto T (outer loop condition)
	M LEN(P) LEN(1) . A			;*A = P'th character of M
	J =Q					;*J is the iteration counter for inner loop
Y	GT(J)	:F(D)				;*if J<=0, goto D (inner loop condition)
	N LEN(J) LEN(1) . B			;*B = J'th character of N
	W =I + J				;*W=I+J, column number in multiplication
	X =G<W> + A * B				;*X=G[W]+A*B, temp variable for golfing
	G<W> =LE(A * B,9) LE(X,9) X	:F(END)	;*if A*B<=9 and X<=9, G[W]=X otherwise terminate with no output
	J =J - 1	:(Y)			;*decrement J, goto Y
D	P =P - 1	:(Z)			;*decrement P, goto Z
T	OUTPUT =				;*set output to ''; OUTPUT automatically prints a newline.
END

2

Вугілля деревне , 38 байт

≔E⁺θη⁰ζFLθFLη§≔ζ⁺ικ⁺§ζ⁺ικ×I§θιI§ηκ‹⌈ζχ

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Виводить a, -коли числа легко помножити. Пояснення:

≔E⁺θη⁰ζ

Ініціалізуйте zдостатньо великий (сума довжин входів) масиву нулів.

FLθFLη

Проведіть петлю над показниками входів qта h.

§≔ζ⁺ικ⁺§ζ⁺ικ×I§θιI§ηκ

Виконайте один крок довгого множення.

‹⌈ζχ

Перевірте наявність кошиків.



2

Хаскелл, 82 81 байт

q=map$read.pure
f a=any(>9).concat.scanr((.(0:)).zipWith(+).(<$>q a).(*))(0<$a).q

Числа, взяті як рядки. Повертається, Falseякщо числа легко помножити та Trueіншим чином.

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

Я думаю, що це досить відрізняється від відповіді @ Лайконі . Як це працює:

q                    -- helper function to turn a string into a list of digits

f a =                -- main function, first number is parameter 'a' 
      scanr    .q    -- fold the following function from the right (and collect
                     -- the intermediate results in a list) into the list of
                     -- digits of the second number
            0<$a     --   starting with as many 0s as there are digits in 'a'
                     -- the function is, translated to non-point free:
  \n c->zipWith(+)((*n)<$>q a)$0:c 
                     -- 'n': next digit of 'b'; 'c': value so far
        (*n)<$>a     --    multiplay each digit in 'a' with 'n'
        0:c          --    prepend a 0 to 'c'
        zipWith(+)   --    add both lists element wise
                     --    (this shifts out the last digit of 'c' in every step)
   concat            -- flatten the collected lists into a single list
 any(>9)             -- check if any number is >9

Приємне рішення! Я шукав способів позбутися імпорту, але вони закінчилися ще довше.
Лайконі

2

Haskell , 45 44 байт

Редагувати:

  • -1 байт змінюється ==на< .

Я подумав про це, перш ніж подивитись інші відповіді, а потім виявив, що Аліса використовувала ту саму основну ідею. Публікація все одно, оскільки вона коротша, ніж інші відповіді Haskell.

?приймає два цілих числа і повертає a Bool. Використовувати як 331?1021. Falseозначає, що множення є простим.

a?b=s(a*b)<s a*s b
s=sum.map(read.pure).show

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

  • s- це функція, яка обчислює суму цифр цілого числа. (read.pure перетворює одноцифровий символ у ціле число.)
  • Якщо пару чисел легко помножити, то цифрова сума добутку дорівнює добутку цифрних сум.
  • І навпаки, будь-яке перенесення під час тривалого множення зменшить розрядну суму товару від цього ідеального.




1

Желе , 8 байт

;PDḄµṪ⁼P

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

Порт моєї відповіді на Javascript . Не коротше існуючої відповіді на желе желе, тому що в желе вбудована потужна згортка.

Візьміть дані як список двох чисел. Повертається 1просто,0 не просто.


Пояснення:


;PDḄµṪ⁼P     Main link. Let input = [101, 99]
;P           Concatenate with product. Get [101, 99, 9999]
  D          Convert to decimal. Get [[1,0,1], [9,9], [9,9,9,9]]
   Ḅ         Convert from binary. Get [1 * 2^2 + 0 * 2^1 + 1 * 2^0, 
             9 * 2^1 + 9 * 2^0, 9 * 2^3 + 9 * 2^2 + 9 * 2^1 + 9 * 2^0]
             = [5, 27, 135]
    µ        With that value,
     Ṫ       Take the tail from that value. Get 135, have [5, 27] remain.
      ⁼      Check equality with...
       P       The product of the remaining numbers (5 and 17).

1

C (gcc) , 104 байти

В основному зробіть множення "від руки" на r [] і встановіть значення повернення, якщо будь-який стовпець стає вище 9, оскільки це означатиме, що відбулося перенесення.

Дивно, але це було коротше, ніж моя перша спроба, яка спричинила аргументи.

f(a,b){int*q,r[10]={0},*p=r,R=0,B;for(;a;a/=10)for(q=p++,B=b;B;B/=10)R|=(*q+++=a%10*(B%10))>9;return R;}

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

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