Розділіть і розділіть і завоюйте


22

Іноді, коли я складно намагаюся підрахувати будь-яке число, яке спливе перед мною¹, через деякий час я розумію, що це простіше, ніж я думав. Візьмемо 2156для прикладу: мені врешті-решт здається, що обидва 21і 56є кратними 7, і так, безумовно 2156 = 21 x 100 + 56, також є кратним 7.

Ваше завдання - написати якийсь код, який ідентифікує числа, які легше визначити через збіг такого роду.

Точніше:

Напишіть програму або функцію, яка приймає позитивне ціле число nяк вхідне, і повертає істинне значення, якщо існує дільник d(більший за 1), такий, який nможе бути розрізаний на два, щоб отримати два додатних цілих числа, кожне з яких є кратним d; повернути помилкове значення, якщо ні.

  • "Розрізаний на два" означає те, що ви думаєте: звичайне представлення бази-10 nв якомусь моменті розділене на передню половину і задню половину, щоб отримати два інших цілих бази-10. Це нормально , якщо друге число має провідне число (але врахуйте , що він повинен бути позитивним цілим числом, так розщепленню 1230в 123і 0не діє).
  • Цінні і хибні значення можуть залежати від вхідних даних. Наприклад, якщо якесь ненулеве ціле число є істинним у вашій вибраній мові, ви можете повернути дільник dабо один із "шматочків" n(або nсебе з цього приводу).
  • Наприклад, будь-яке парне число з принаймні двома цифрами в наборі {2, 4, 6, 8}дасть триєдне значення: просто розділіть його після першої парної цифри. Наприклад, наприклад, будь-яке просте число nдасть помилкове значення, як і будь-яке одноцифрове число.
  • Зауважте, що достатньо розглянути основні дільники d.
  • Ви можете вважати, що введення дійсне (тобто додатне ціле число).

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

Тестові кейси

(Потрібно вивести лише значення "фальшива" чи "хибна"; наведені нижче пояснення пояснюються лише поясненнями.) Деякі вхідні дані, які дають значення "truthy":

39  (3 divides both 3 and 9)
64  (2 divides both 6 and 4)
497  (7 divides both 49 and 7)
990  (splitting into 99 and 0 is invalid; but 9 divides both 9 and 90)
2233  (11 divides both 22 and 33)
9156  (3 divides both 9 and 156; or, 7 divides both 91 and 56)
11791  (13 divides both 117 and 91)
91015  (5 divides both 910 and 15)
1912496621  (23 divides both 1912496 and 621; some splittings are multiples of 7 as well)
9372679892  (2473 divides both 937267 and 9892; some splittings are multiples of 2 as well)

Деякі входи, які дають помилкові значення, є:

52
61
130  (note that 13 and 0 is not a valid splitting)
691
899
2397
9029
26315
77300  (neither 7730 and 0 nor 773 and 00 are valid splittings)
2242593803

¹ так, я дійсно це роблю

Відповіді:


7

Сітківка , 31 29 байт


,$';$`
\d+
$*
;(11+)\1*,\1+;

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

Виводить додатне ціле число для дійсних входів та нульове для недійсних.

Я б не рекомендував чекати на більші тестові справи ...

Пояснення


,$';$`

У кожну позицію введення вставляйте кому, потім усе перед цією позицією, потім крапкою з комою, а потім все після цієї позиції. Що це робить? Це дає нам усі можливі розбиття числа (розділити на ,, розділені на ;), а потім введення знову в кінці. Так вхід 123стає

,123;1,23;12,3;123,;123
     ^     ^     ^

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

\d+
$*

Перетворіть кожне число в одинакове.

;(11+)\1*,\1+;

Зрівняйте розділення, зіставивши обидві половинки як кратні деякого числа, що принаймні 2.


Швидке запитання щодо Retina: Що робить провідний новий рядок?
HyperNeutrino

@HyperNeutrino Добре, що перший рядок - це перший регекс, з яким ми співставляємось, і ми хочемо відповідати порожньому регулярному вираженню, щоб вставити підстановку у кожну позицію між символами.
Мартін Ендер

О, гаразд. Спасибі! Мені, мабуть, варто було б трохи придивитись до Retina; так як це, здається, значною мірою на основі регулярних виразів, це може бути корисним для проблем складності колмогорів .
HyperNeutrino

Чи міг би бути останній рядок;(11+)+,\1+;
Райлі

@ Райлі, що не гарантує, що перший сегмент є кратним одному фактору.
Мартін Ендер

6

Брахілог (2), 8 байт

~c₂ḋᵐ∋ᵐ=

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

Пояснення

~c₂ḋᵐ∋ᵐ=
~c₂       Split the input into two pieces
    ᵐ ᵐ   On each of those pieces:
   ḋ ∋      Choose a prime factor
       =  such that both the chosen factors are equal

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

Не потрібно перевіряти відповідність внутрішніх нулів; якщо розкол xі 0yдіє, x0і yбуде працювати так само добре (і в іншу сторону, якщо x0і yпрацює, тобто працююче рішення , незалежно від того , xі 0yбуде працювати чи ні).

Повна програма Brachylog, як ця, повертає булеву; true.якщо є якийсь спосіб запустити його без збоїв (тобто зробити вибір таким, щоб не виникало помилок), false.якщо всі шляхи призводять до відмови. Саме цього ми хочемо тут.


4

Желе , 14 12 11 10 байт

ŒṖḌo1g/€P>

Дякуємо @JonathanAllan за те, що виграли 1 байт!

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

Як це працює

ŒṖḌo1g/€P>  Main link. Argument: n

ŒṖ          Compute all partitions of n's decimal digits.
  Ḍ         Undecimal; convert each array in each partition back to integer.
   o1       OR 1; replace disallowed zeroes with ones.
     g/€    Reduce (/) each (€) partition by GCD (g).
            The last GCD corresponds to the singleton partition and will always be
            equal to n. For a falsy input, all other GCDs will be 1.
        P   Take the product of all GCDs.
         >  Compare the product with n.

Я думаю, що ти можеш відмовитись D, як make_digitsце діє ŒṖ.
Джонатан Аллан

Чомусь я припускав, що це створить діапазон ... Дякую!
Денніс

3

Математика, 63 62 байти

(1 байт завдяки Грегу Мартіну)

1<Max@@GCD@@@Table[1~Max~#&/@Floor@{Mod[#,t=10^n],#/t},{n,#}]&

Це функція, яка приймає ціле число як вхід і повернення Trueабо False. Якщо ви перевірите його на великій кількості, принесіть книгу для читання, поки ви чекаєте.

Пояснення:

  • Floor@{Mod[#,t=10^n],#/t}арифметично розбиває вхід на останні nцифри та інші m-nцифри (де mзагальна кількість цифр).
  • Table[1~Max~#&/@...,{n,#}]робить це для кожного nдо вхідного номера. (Це занадто багато. Нам потрібно це робити лише до кількості цифр вхідних даних, але цей спосіб економить байти і все одно дає правильний результат.) 1~Max~#&/@Біт позбавляється від нулів, тому числа, як-от 130 -> {13,0}не враховуються як True.
  • 1<Max@@GCD@@@... знаходить найбільшого спільного дільника кожної з цих пар і перевіряє, чи є один із цих дільників більше 1. Якщо вони є, ми знайшли спосіб підрахувати число, поділивши його.

1
Гарна відповідь! Ви можете зберегти один байт за допомогою {#~Mod~10^n,#/10^n}або {Mod[#,t=10^n],#/t}.
Грег Мартін

Я спробував #~Mod~10^n, але, схоже, замінили, як Mod[#,10]^nзамість Mod[#,10^n]. Я не думав про твою другу пропозицію!
Не дерево

Справедливий пунктMod[#,10]^n
Грег Мартін,


2

С, 145 142 139 138 135 байт

i,a,b;f(){char s[99];scanf("%s",s);for(char*p=s;*p++;)for(b=atoi(p),i=*p,*p=0,a=atoi(s),*p=i,i=1;i++<b;)*s=a%i-b%i|b%i?*s:0;return!*s;}

2

JavaScript (ES6), 74 71 70 байт

f=(s,t='',u)=>u?s%t?f(t,s%t,1):t:s&&f(t+=s[0],s=s.slice(1),1)>1|f(s,t)
<input oninput=o.textContent=f(this.value)><span id=o>

Вводиться в якості рядка, який зручно для фрагмента. Редагувати: збережено 3 байти завдяки @ user81655.


Зберігає два байта: (c,i)-> c, i+1-> ++i, t=''-> i=t='', цей прийом корисний в будь-який час ви повинні використовувати індекси 1-засновані і де - то ініціалізацію iдо 0.
користувач81655

Також я вважаю, що це t=''може бути t=0, оскільки додавання cпримушує його до рядка.
користувач81655

@ user81655 Це сталося тому, що я спочатку нарізав від і до i, тому мені не знадобилися 1-бальні індекси, але потім я переграв перший шматочок t+=c.
Ніл

Ну, тоді добре. Крім того, одна остання річ, я думаю , що це також може бути коротше рекурсивної функції: f=(x,y,z)=>z?x%y?g(y,x%y):y:x?f(x,y,1)>1||f(x.slice(1),~~y+x[0]):0. Я також поєднав вашу функцію GCD f. Можливо, можна було б пограти в гольф далі. Остання пропозиція, обіцяю! : P
користувач81655

@ user81655 На жаль, моя надто спрощена gcdфункція не працює x=0, і коли ця робота і ваш друкарський помилок взяли мене до 72 байт, тож пощастило, що я тоді зміг відіграти 2 байти.
Ніл

2

Python 3, 133 118 117 байт

i,j=int,input()
from fractions import*
print(any(i(j[k:])*i(j[:k])*~-gcd(i(j[k:]),i(j[:k]))for k in range(1,len(j))))

Звичайно, не найкоротший, напевно, можна було б трохи скоротити. Працює в O(n)часі. Введення приймається у форматі, \d+а вихід подається у форматі (True|False)за типовим бутовим значенням Python
-3 байти завдяки Dead Possum
-15 байт завдяки ovs
-1 байту завдяки цьому хлопцю


from fractions import*врятувало б 3 байти
Dead Possum

Це повертає True за 900. Я думаю, це неправильно. Мб ви повинні змінити внутрішнє anyдо all? Якщо це так, ви можете змінити всю цю частину, i(j[k:])and i(j[:k])довівши її до 125 байт. Ось виправлення
Dead Possum

Ви можете замінити і і все множенням:any(i(j[k:])*i(j[:k])*~-gcd(i(j[k:]),i(j[:k]))for k in range(1,len(j)))
ов

@DeadPossum О так, я мав би це зробити. Так, у моєму теперішньому методі є багато гольфуючих частин, але я буду дотримуватися пропозицій ovs. Дякуємо, що вказали на це! (насправді я повинен був перевірити це сам ... ну добре ...)
HyperNeutrino

Ви можете видалити байт (майже нічого), видаливши пробіл між)) for
caird coinheringaahing

1

QBIC , 91 90 байт

;_LA|[a-1|B=left$(A,b)┘C=right$(A,a-b)┘x=!B!┘y=!C![2,x|~(x>1)*(y>1)*(x%c=0)*(y%c=0)|_Xq}?0

Пояснення:

;               Get A$ from the command prompt
_LA|            Get the length of A$ and place it in a% (num var)
[a-1|           for b%=1; b% <= a%-1; b%++
B=left$(A,b)    break A$ in two components on index b%
C=right$(A,a-b)
x=!B!┘y=!C!     Convert both parts from string to num, assign to x% and y%
[2,x|           FOR c% = 2; c% <= x%; c%++

This next IF (~ in QBIC) is a bit ... iffy. It consists of a set of comparators.
Each comparator yields a -1 or a 0. We take the product of these. At any failed
comparison this will yield 0. When successful, it yields 1, which is seen as true by QBasic.

~(x>1)*(y>1)        IF X>1 and Y>1 --> this stops '00' and '1' splits.
*(x%c=0)*(y%c=0)    Trial divide the splits on loop counter c%.

|_Xq            Success? THEN END, and PRINT q (which is set to 1 in QBIC)
}               Close all language constructs (2 FOR loops and an IF)
?0              We didn't quit on match, so print 0


1

Perl 5 , 46 байт

43 байти коду + 3 байти для -pпрапора.

s~~$\|=grep!($`%$_|$'%$_),2..$`if$`*$'~ge}{

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

Пояснення:
Ми повторюємо кожну позицію у слові з s~~~g, $`містить цифри до і $'цифри після. Якщо $`*$'вірно (це означає, що жоден не порожній, і жоден немає 0), тоді ми перевіряємо, чи є число між 2 і $`ділить їх обоє (на grep!(...),2..$`). Якщо це так, $\|=..буде встановлено $\ненульове значення, яке неявно друкується в кінці завдяки -pпрапору.


2
Якщо хтось знає, як відобразити $<backquote>відмітку в SE, я буду вдячний, якщо ви мені скажете як.
Дада

1
Ви можете зробити це за допомогою явних <code></code>(а не ``), а потім уникнути зворотних котирувань як \`. Також цей коментар було боляче писати, оскільки його потрібно подвійно уникати (а два набори правил утечі відрізняються!).

@ ais523 Чудово, дякую дуже! :)
Дада

0

Python 2 , 69 байт

f=lambda n,d=10,k=2:k<d<n and(n/d%k+n%d%k<1<n%d)|f(n,d,k+1)|f(n,10*d)

Використовується рекурсія замість вбудованих GCD.

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

Як це працює

Коли f викликається одним-трьома аргументами ( d за замовчуванням до 10 , k до 2 ), він спочатку перевіряє значення виразу k<d<n. Якщо нерівності k <d і d <n мають місце, вираз, що слідує, andвиконується і його значення повертається; інакше f просто поверне помилковий .

У першому випадку ми починаємо з оцінки виразу n/d%k+n%d%k<1<n%d.

d завжди буде потужністю десять, тому n/dі n%dефективно розділіть десяткові цифри на n на два відрізки. Ці зрізи поділяються як на k, якщо і лише тоді, коли n/d%k+n%d%kоцінюють на 0 , що тестують шляхом порівняння результату з 1 .

Оскільки частина вимог полягає в тому, що обидва зрізи повинні представляти додатні цілі числа, значення n%dтакож порівнюється з 1 . Зауважте, що 1 не має простих дільників, тому дорожче порівняння з 0 не потрібно. Також зауважте, що d <n вже гарантує, що n/dбуде оцінено до додатного цілого числа.

Нарешті, це рекурсивно всі f(n,d,k+1)(намагаючись наступний потенційний спільний дільник) і f(n,10*d)(спробу розщеплення) і повертає логічний АБО всіх трьох результатів. Це означає, що f поверне значення True, якщо (і лише тоді, коли) k є спільним дільником n / d і n% d або те ж саме справедливо для більшого значення k та / або більшої потужності в десять d .

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