Простые в умножении числа


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

Leaderboard:


1
Может ли ввод для каждого номера быть списком цифр?
Дилнан

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

Ответы:


14

Желе , 7 байт

Dæc/>9Ẹ

Попробуйте онлайн!

Использует свертку (которую я внес в желе: D)

Как это работает

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

о вау свертка: D я думаю, что я впервые вижу свертку, используемую в код-гольфе: D +1
HyperNeutrino



@ LuisMendo Нет, это другая свертка.
Эрик Outgolfer

Кстати, вы можете заменить последние 3 байта <⁵Ạдля вывода без логического НЕ выполняется.
Эрик Outgolfer

8

JavaScript (ES6), 67 байт

Принимает ввод как 2 строки в синтаксисе карри (a)(b). Возвращает falseлегко или trueне легко.

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

Контрольные примеры


Чередующийся версия (ошибочная), 64 55 52 байта

Сохранено 3 байта путем взятия строк, как предложено @Shaggy
Как указывалось @LeakyNun, этот метод завершится с ошибкой на некоторых больших конкретных целых числах

Принимает ввод как 2 строки в синтаксисе карри (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)

Попробуйте онлайн!

Принимает ввод как строки.

Это некрасиво, но это работает ™.

Теперь в нем используется метод свертки, как в ответе Лики Нун , поэтому он принимает входные данные в виде целых чисел и возвращает 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 .
Деннис


Это не на 400, 300 . len(`n`+`m`)должен сделать хотя.
Деннис

4

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

Спасибо @ Dennis за идею использования интерполяции строк в этом ответе и сэкономьте 4 байта!

Спасибо @ ÖrjanJohansen за -1!

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

Попробуйте онлайн!

Конечно, когда база назначения меньше, чем исходная база (как в моем ответе на желе, база равна 2), <необходимо щелкнуть.


Поздравляю с тем, что первым решил использовать базовую конверсию, за которую я даю вам награду!
xnor

3

Wolfram Language (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 за использование инфиксного оператора

-9 Спасибо @MartinEnder за Maxфункцию


3

Python 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: одна новая строка для простого умножения и отсутствие вывода для простого умножения.

Это не принесет никаких наград, но представляет другой подход (ну, на самом деле, это наивный подход). Я не думаю, что смогу написать это в cubix, но SNOBOL достаточно сложен, чтобы работать с ним как есть.

Так как он принимает ввод как строку, он будет работать для любого ввода, содержащего менее 512 цифр каждый; Я не уверен на 100%, насколько большойARRAY может быть СНОБОЛ.

В этой версии SNOBOL INPUT буферизуется с максимальной шириной 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§ηκ‹⌈ζχ

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

≔E⁺θη⁰ζ

Инициализируйте zдостаточно большой (сумма длин входов) массив нулей.

FLθFLη

Цикл по показателям входов qи h.

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

Выполните один шаг длинного умножения.

‹⌈ζχ

Проверьте для выполнения.



2

Haskell, 82 81 байт

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

Числа взяты как строки. Возвращает, Falseесли числа легко умножить и в Trueпротивном случае.

Попробуйте онлайн!

Я думаю, что это достаточно отличается от ответа @ Laikoni . Как это работает:

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

Хаскелл , 45 44 байта

Редактировать:

  • -1 байт меняется ==на <.

Я подумал об этом, прежде чем посмотреть на другие ответы, а затем обнаружил, что Алиса использовала ту же основную идею. Публикация в любом случае, так как она короче, чем другие ответы на Haskell.

?принимает два целых числа и возвращает 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 ответа . Не короче существующего желе ответ, потому что Jelly имеет мощную встроенную свертку.

Принять ввод как список из двух чисел. Возвращается 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.