Ділиться на 1000003? Легко, просто помножте останню цифру на 300001 і додайте!


16

З урахуванням простої величини, Pніж 10ваша програма або функція повинна визначити своє правило поділу x, визначене як ціле число з найменшим абсолютним значенням, яке дає кратне значення початкового розмноження, помножене на останню цифру простих і додане до решти оригіналу прем'єр.

Приклад

Враховуючи вхід 31, остання цифра є, 1а решта числа - 3. Таким чином, ваша програма повинна знайти ціле число xз мінімальним абсолютним значенням, таким, яке 1*x + 3кратне кратному 31. У цьому випадку x=-3працює, тому програма чи функція повернуться -3.

Враховуючи вхід 1000003, остання цифра є, 3а решта числа - 100000. Таким чином, ваша програма знайде x=300001тому, 3*300001+100000 = 1000003що є кратним 1000003.

Математичні передумови

Значення xможе бути використане як тест на роздільність. Якщо число Nділиться на P, то додавання xразів останньої цифри Nдо решти Nбуде давати кратне значення, Pякщо і тільки, якщо Nвоно ділене на, Pв першу чергу.

Бо P=11ми отримуємо x=-1, що еквівалентно відомому правилу ділення 11: число ділиться шляхом 11чергування різниці його цифр, що ділиться на 11.

Правила

  • Вихід може бути в будь-якій формі, яка чітко кодує як знак, так і значення результату.
  • Вхідний простір буде від 10 до 2 ^ 30.
  • Не потрібно обробляти, якщо вхід не є простим або не знаходиться в діапазоні.
  • Вам не потрібно обробляти, якщо обидва xі -xє дійсними результатами (не повинно відбуватися).
  • Груба сила дозволена, але більш творчі рішення цінуються.
  • Це , тому найкоротший код на кожній мові виграє! Не дозволяйте відповіді на гольф-мовах відштовхувати вас від публікації іншими мовами.

Випробування

Input   Output
11  -1
13  4
17  -5
19  2
23  7
29  3
31  -3
37  -11
41  -4
43  13
47  -14
53  16
59  6
61  -6
67  -20
71  -7
73  22
79  8
83  25
89  9
97  -29
101 -10
103 31
107 -32
109 11
113 34
127 -38
131 -13
1000003 300001
2000003 600001
2999999 300000
9999991 -999999

3
Корисне спрощення: ми шукаємо найменше xза абсолютною величиною, де 10*x-1ділиться на вхід.
xnor

Чи може хтось надати підказку, чому (3 / (n % 5 * 2 - 5) * n + 1) / 10і (n % 5 * 2 - 5^2) * n / 10 + 1чи здатний знайти мінімальне абсолютне значення для чогось подібного? Моєю першою інтуїцією було б обчислити найменше спільне кратне, використовуючи найбільший спільний дільник, обчислений за алгоритмом Евкліда.
Девід Фоерстер

1
@DavidFoerster Враховуючи число, ви можете видалити останню цифру, помножити її на число x, додати її та все одно отримати число, що ділиться на n. Якщо ми помножимо нове число на 10 і віднімемо початкове число, воно все ще залишається діленим на n. коментар xnor потім випливає з деякої алгебри. Наступний крок - переставити формулу так, щоб вона давалась xу вигляді n: x = (k*n+1)/10. Ми хочемо , щоб найменше абсолютне xтак тому ми хочемо , щоб найменше абсолютне k, і це повинно бути в залежності від того один з -3, -1, 1або 3( в залежності від n«s остання цифра) , що робить поділ точним.
Ніл

Відповіді:


14

JavaScript (ES6), 32 25 23 байт

f=
n=>(3/(n%5*2-5)*n+1)/10
<input type=number min=1 oninput=o.textContent=this.value%5*(this.value%2)?f(this.value):``><pre id=o>

3/(n%5*2-5)було б написано, 9/n(mod -10)якби у мене був доступ до збалансованого поділу модулів. Редагувати: збережено 2 байти завдяки @EgorSkriptunoff


3
Ви можете зберегти 2 байти, замінивши n=>((n%10*2%14-3)*n+1)/10зn=>(3/(n%5*2-5)*n+1)/10
Єгор Skriptunoff


@KevinCruijssen Напевно, поліглот, який майже не вистачає, для Java 8 теж ... о, чекайте, зараз я бачу вашу відповідь!
Ніл

@Neil Ти маєш рацію. Я зазвичай публікую відповіді на Java, тому я вже працював над портом xnor, коли побачив вашу відповідь. Опублікував це так чи інакше, як нудний порт, який кредитує вас.
Kevin Cruijssen

8

Python 2 , 27 байт

lambda n:(n%5*2-5^2)*n/10+1

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

Операції виконуються зліва направо: (((n%5)*2)-5)^2.

Я використовував свій арифметичний грубий форссер, щоб знайти вираз n%5*2-5^2для виконання {1:-1,3:3,2:-3,4:1}[k], виводячи негативну інверсію залишку mod 5 в діапазон [-2..2].


Чи є дещо доступним цей арифметичний грубий форцер?
Лінн

Це єдиний вираз, який він знайшов, чи він просто надрукує перший із заданої довжини? ( 3/(n%5*2-5)така ж довжина, як і (n%5*2-5^2).)
Ніл

@Lynn Ні, я можу прибрати та виправити його та розмістити, коли встигну.
xnor

1
@Neil Він знайшов лише еквіваленти та n%5*2-6^3 . Я лише дивився на довжину, хоч вираз без паронів, тоді 3/(n%5*2-5)як два символи довші, але економив на зовнішніх паролях через перевагу. Пошук виразів такої довжини повинен зайняти деякий час. Цей випадок використання пропонує можливість знайти лише вирази, які можуть бути використані в заданому контексті за допомогою їхньої зовнішньої операції з достатньо високим пріоритетом.
xnor

6

Желе ,10 8 байт

,N⁵æiAÞḢ

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

Пояснення

,N       Get [Input, -Input].
⁵æi      Modular inverse of 10 mod each of [Input, -Input].
AÞ       Sort by absolute value.
Ḣ        First.

+1 Я ніколи не бачив подання Jelly з реєстром, який фактично економить байти
Містер Xcoder

@ Mr.Xcoder Це було тому, що я не грав у нього добре.
jimmy23013


5

Пітон 2 , 69 54 53 байт

Редагувати: -15 байт завдяки @ Mr.Xcoder

Редагувати: -1 байт за допомогою рекурсії

f=lambda a,x=-1:(a%10*x+a/10)%a and f(a,-x-(x>0))or x

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


54 байта . Я не бачу, чому у вас є ці змінні, коли ви використовуєте їх лише один раз
містер Xcoder

Так, трохи поспішав, коли я написав це
Халвард Гуммель


5

Japt , 16 9 байт

Заощаджено занадто багато байтів завдяки спостереженню @xnor

_*AÉ vU}c

Перевірте це в Інтернеті! На великих входах може зайняти пару секунд.

Пояснення

_  *AÉ  vU}c    Implicit: U = input integer
Z{Z*A-1 vU}c    Ungolfed
Z{        }c    Loop through each integer Z in [0, -1, 1, -2, ...] and yield the first where
  Z*A             Z times 10
     -1           minus 1
        vU        is divisible by the input.
                Implicit: output result of last expression

2

Java 8, 23 21 байт

n->3/(n%5*2-5)*++n/10

Порт @Neil JavaScrip (ES6) відповідь «s , але -2 байт завдяки @Nevay з - за неявного Настил цілих чисел.

Спробуйте тут.


1
21 байт:n->3/(n%5*2-5)*++n/10
Невай

1
@Nevay Навіть коли я створити порт верхнього відповіді, ви все одно повинні гольфі мене .. XD (Читати: Дякую і хороша робота)
Кевін Cruijssen



1

Python 2 , 44 43 байт

(Закреслено 44 ще 44.) Завдяки Fireflame241 за збереження байта!

P=input();i=P/3
while i*10%P-1:i-=1
print i

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

Існує рівно одне число між 0і P-1яке є оберненим 10. Але якщо ця обернена величина uбільша за P/2, то (u-P)це також обернена і має менше абсолютне значення, ніж u. Так виходить, що ми дійсно шукаємо унікальне число xміж ними-P/2 і P/2яке є зворотним10 .

Код, що вводиться вище, робить саме це, починаючи з (поверху) P/2і відступаючи доти, доки не буде досягнуто зворотного. Це повинно відбуватися на деяку кількість, більший за той -P/2час, коли Pпрайм більший за 10. Точніше, він припиняється, якщо і лише тодіP є спільним 10.

Редагувати: насправді виявляється, що xвін гарантовано знаходиться між -P/3і P/3, тому поточна версія починається з P/3та знижується звідти. Для пояснення цього див. Розділ з поліпшеною межею .

Математичне пояснення

Мені було не відразу зрозуміло, чому працює тест на подільність. Ось пояснення, на випадок, якщо хтось ще задумався.

Нехай Pбуде простим, більшим за 10, чия остання цифра b. Таким чином

P = 10a + b

де a > 0і 0 <= b < 10. Насправді bабо 1, 3, 7, або 9, так як просте число , більше 10має закінчуватися в одній з цих цифр.

Тепер припустимо bx + a = 0 (mod P). Потім

a = -bx (mod P)

10a + b = 10(-bx) + b (mod P)

0 = 10(-bx) + b (mod P)

0 = b(1 - 10x) (mod P)

Оскільки Pє простим, цілі числа mod Pє цілісною областю . Так чи b = 0 (mod P), або1 - 10x = 0 (mod P) .

Ми знаємо 0 <= b < 10 < P, так, якщо b = 0 (mod P)тоді b = 0. Але ми сказали , bабо 1, 3, 7, або 9, так що це неможливо. Тому 1 - 10x = 0 (mod P)так 10x = 1 (mod P). Іншими словами, xце зворотне значення 10модуля P.

Припустимо N, це невід’ємне ціле число, остання цифра якого є d, тому у N = 10c + d. нас є ланцюжок еквівалентних висловлювань:

10c + d = 0 (mod P)

<==> 10xc + dx = 0 (mod P)

<==> c + dx = 0 (mod P)

QED.

Корисність?

Мені було також цікаво чи тест подільності (враховуючи N = 10c + d, замінити Nна dx + c) буде на самому ділі бути продуктивним на практиці. Або, принаймні, чи надійно його замінює Nна число, менше ніжN (в абсолютній величині)?

Припустимо N = 10c + d, де c >= 0і 0 <= d < 10. Тому 10c = N - d <= N. За нерівністю трикутника,

|c + dx| <= |c| + |dx| = c + d|x| <= N/10 + d|x|

< N/10 + 10|x| <= N/10 + 10P/2 = N/10 + 5P

Таким чином, якщо 5P <= 9N/10, то |c + dx| < N.

Зокрема, якщо N >= 6P, то |c + dx| < N. Таким чином, з огляду на , Pми почнемо з розрахунку 2P, 3P..., 6Pпоряд з x. Потім дається N, ми проводимо тест делімостних кілька разів , поки ми не досягнемо числа менше або дорівнює 6P, і перевірити , є чи результат будь-якої з чисел 0, P, 2P..., 6P.

(Зрозуміло, щоразу, коли ми досягаємо від’ємного числа, ми замінюємо його абсолютним значенням, яке добре, оскільки qділиться на Pтоді і лише тоді, коли (-q)є.)

Поліпшене обмеження

Я помітив, що |x|/Pніколи не здавалося, що поруч 1/2. Насправді здавалося, що це завжди менше, ніж 1/3... або при більш детальному огляді це завжди було дуже близько до 1/10або 3/10. Найбільшим, що коли-небудь було, здавалося, 4/13що буває (коли P=13і коли x=4). Чому це було б?

Нехай uбуде цілим числом, і припустимо, що 10u = kP + 1для деякого цілого числа k, так uце обернено 10модуль P. Тоді ми також знаємо, що kє відносно простим 10, оскільки k(-P)еквівалентно 1модулю10 .

Тепер ми знаємо, що всі звороти 10модуля Pрізняться кратними величинами P, тому ми можемо взяти ціле число uі або додавати, або віднімати кратні Pза бажанням, і результат завжди буде інверсійним за 10модулем P. Припустимо , що ми вибираємо , щоб відняти Pз u: ми отримуємо

10(u - P) = 10u - 10P = kP + 1 - 10P

10(u - P) = (k - 10)P + 1

Іншими словами, зменшення (відповідно, збільшення) uна Pвідповідно зменшується (збільшується) kна 10. Ми хочемо додати / відняти кратні Pз, uпоки ліва частина не буде мінімізована в абсолютній величині; але лівий бік зведений саме тоді, коли правий бік зведений до мінімуму, і тому ми хочемо додавати / віднімати 10з kтих пір, поки правий бік не буде мінімізований в абсолютне значення.

Але ми знаємо , що це станеться , коли kміж -5і 5, і , отже , (так як kвзаємно просте з 10) це означає , що kабо -3, -1, 1або 3. (Це вміст коментаря @ Ніла в рамках ОП. Дякую, Ніл! )

Таким чином , коли |u|мінімізується (тобто u=x), ми будемо мати x/P = u/P = k/10 + 1/(10P), де kабо -3, -1, 1або 3. Тому |x|/P <= 3/10 + 1/(10P). Рівнозначно , |x| <= (3P + 1)/10.

Далі ця нерівність сувора в P=11тому, що в P=11нас є x=-1і k=-1. Найменший розмір, Pна який дотримується рівність, є P=13(де x=4і k=3).

Тому найбільший, що |x|/Pколи-небудь отримує 3/10 + 1/(10*13), тому що P=13це перший прайм, який ми маємо k=3, і серед тих, хто має k=3, 1/(10P)термін найбільший, коли Pнайменший (тобто, в P=13). Тому для всіх у Pнас теж є |x|/P <= 3/10 + 1/130 = 4/13 < 1/3. Це пояснює, чому у наведеному вище коді ми можемо ініціалізуватись, i = P/3а не потрібно починати P/2.

Крім того, межі в розділі Корисність вище можна тепер покращити.

Лема : Нехай N = 10c + dде c > 0і де 0 <= d <= 9. Потім c + d|x| < N/10 + 9(3P + 1)/10. (Зверніть увагу на сувору нерівність.)

Доведення леми: по випадках. Випадок I: d = 0так N = 10c. Потім c + d|x| = c = N/10 < N/10 + 9(3P + 1)/10.

Випадок II: 0 < d <= 9. Тоді 10c = N - d < N, так c < N/10. Томуc + d|x| < N/10 + d|x| <= N/10 + 9|x| <= N/10 + 9(3P + 1)/10 . QED.

Таким чином, якщо N > 3PN = 10c + dяк і раніше), то

3P + 1 <= N

9(3P + 1)/10 <= 9N/10

N/10 + 9(3P + 1)/10 <= N

c + d|x| < N/10 + 9(3P + 1)/10 <= N

Отже, якщо N > 3Pтоді c + d|x| < N.

Тому нам залишається лише знайти P, 2Pі 3Pразом з x. Враховуючи N > 0, поки N > 3Pми замінюємо Nна |c + dx|, що зменшується N. Врешті-решт ми отримаємо N <= 3P; в цій точці ми зупиняємося і перевірити , є чи Nодно жодному з чисел 0, P, 2Pабо3P .

Ми не можемо зробити краще, ніж 3Pзагалом. Наприклад припустимо P = 13і N = 39так x = 4. Потім замінити Nна dx + c = 9(4) + 3листя Nбез змін.


Дуже приємне пояснення! Ви можете зберегти байт, перемістившись -1поза дужки: 43 байти
fireflame241

@ fireflame241 Дуже дякую! Я міг би стверджувати, що залишив його в 44 роки, щоб я міг перекреслити його (хоча це було б неправдою).
mathmandan

1

Пробіл , 92 байти

Зауважте, що синтаксис цієї мови складається лише з пробілу , тому кожен символ пробілу тут встановлений з префіксом S, T або L (що відповідає пробілу, Tab та Linefeed відповідно). Їх можна видалити, не втрачаючи функціональності, але вони включені сюди, щоб правильно відобразити їх.

S S S L
T   L
T   T   S S S L
T   T   T   S L
S S S S T   T   L
T   S S L
S L
T   S S S T S T L
T   S T T   S L
S T S S S S S S T   S T L
T   S S T   T   S T S S S S T   L
T   S S S S S S T   S T S L
T   S T S T L
S T L
L
L
.

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




0

Excel, 27 байт

=0.3/(MOD(A1,5)*2-5)*A1+0.1

Можна ввести в Cell як

=.3/(MOD(A1,5)*2-5)*A1+.1

на 25 байт, але автоматичні оновлення Excel.


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