Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Что происходит в задачке? (https://javascript.ru/forum/misc/83062-chto-proiskhodit-v-zadachke.html)

orloff 05.09.2021 01:51

Что происходит в задачке?
 
Всем привет.
На Codewars есть задачка
Given n, take the sum of the digits of n. If that value has more than one digit, continue reducing in this way until a single-digit number is produced. The input will be a non-negative integer.

Пример
16 --> 1 + 6 = 7
942 --> 9 + 4 + 2 = 15 --> 1 + 5 = 6

Я ее честно решил с рекурсией, но потом поискал другие решения и нашел код в одну строку
export const digitalRoot = (n:number): number => {
 // your code here
    return (n - 1) % 9 + 1;
};

Расскажите плиз неучу, что происходит? Мы отнимаем 1 от нашего числа, получаем остаток от деления на 9, и плюсуем единицу. И это подходит к любому числу. Что это вообще за трюк?

Aetae 05.09.2021 01:56

Ну вот такая вот закономерность. Ответы искать в институтской программе теории числел. Не думаю что тут найдётся спец по вопросу.)

orloff 05.09.2021 02:23

Aetae,
Спасибо за ответ. Думал может кто помнит/знает. Уж очень джедайское решение получилось)) Хотя это не решение задачи, а скорее задача под эту закономерность заточена )

Aetae 05.09.2021 03:00

Так тоже верно, кстати:
const digitalRoot = (n, base = 10) => {
    return (n - 1) % (base - 1) + 1;
};
:)

MallSerg 05.09.2021 13:54

Это вроде "Арифметика остатков" из теории чисел

Alexandroppolus 05.09.2021 18:32

Цитата:

Сообщение от orloff
Что это вообще за трюк?

навскидку, немного коряво, но тем не менее.

1) Число делится на 9, если сумма его цифр делится на 9 (признак делимости, можно глянуть в википедии). Т.е. если у нас исходное число М = 9*N, то очевидно, digitalRoot придет к 9.

2) Теперь кейс, когда наше число не делится на 9, то есть равно М = 9*N + k, где k=1..8, или, по другому, M % 9 = k
Здесь можно легко доказать, что сумма цифр будет сохранять остаток от деления на 9, при выполнении digitalRoot, на каждой итерации.

Пусть последняя цифра числа 9*N оказалась равна m. Добавим k. Если m + k < 10, то просто последняя цифра увеличилась на k. Иначе, последняя цифра стала равна m + k - 10, стоящие перед ней n девяток обнулились, а недевятка перед ними увеличилась на 1. Сумма цифр поменялась на (m + k - 10) - m - n*9 + 1 = k - 9*p. То есть в любом случае остаток суммы цифр от деления на 9 стал равен k. Что, собственно, и доказывали.

Вот так и вышло, что сохраняя оный остаток, digitalRoot приходит либо к 9 в случае нулевого остатка, либо. самому остатку.

Alexandroppolus 05.09.2021 18:52

Сейчас подумал, что п.1 не более чем частный случай п.2, только для нулевого остатка. В общем, всё доказательство в п.2

MallSerg 05.09.2021 19:27

Такие вещи проще всего объяснять графически.

Взять базу 9 и отобразить ее в виде типа циферблата часов с делениями от нуля до девяти.
Числовую прямую намотать на такой циферблат в виде спирали согласно делениям.
Тогда станет хорошо заметно что к примеру число 10 будет на линии первого деления циферблата а число 20 на втором делении циферблата а к примеру число 14 будет на пятом делении потому что 10 начинается на первом делении и плюс еще четыре деления, число 24 будет на 6м делении циферблата и.т.д. Это пример с десятками, с сотнями тысячами и так далее работает абсолютно аналогично.

Если разобрать по шагам то станет понятно почему это работает для любого числа
и почему в условиях задачи число не должно превышать базу.

рони 07.09.2021 09:32

MallSerg,
:thanks:


Часовой пояс GMT +3, время: 12:53.