Проверьте, является ли число делимым на 3
Введите код, чтобы определить, делится ли число на 3. Вход в функцию представляет собой бит одиночный, 0 или 1, а выход должен быть 1, если число, полученное до сих пор, является двоичное представление числа, делящегося на 3, в противном случае - 0.
Примеры:
input "0": (0) output 1
inputs "1,0,0": (4) output 0
inputs "1,1,0,0": (6) output 1
Это основано на вопросе интервью. Я прошу рисовать логические ворота, но поскольку это stackoverflow, я соглашусь с любым языком кодирования. Бонусные баллы за аппаратную реализацию (verilog и т.д.).
Часть a (легко):. Первый вход - это MSB.
Часть b (немного сложнее): Первый ввод - это LSB.
Часть c (трудная): Какая из них быстрее и меньше, (a) или (b)? (Не теоретически в смысле Big-O, но практически быстрее/меньше.) Теперь возьмите более медленный/больший и сделайте его быстрым/маленьким, чем более быстрый/меньший.
Ответы
Ответ 1
Хех
Таблица состояний для LSB:
S I S' O
0 0 0 1
0 1 1 0
1 0 2 0
1 1 0 1
2 0 1 0
2 1 2 0
Объяснение: 0 делится на три. 0 << 1 + 0 = 0
. Повторяйте с помощью S = (S << 1 + I) % 3
и O = 1
, если S == 0
.
Таблица состояний для MSB:
S I S' O
0 0 0 1
0 1 2 0
1 0 1 0
1 1 0 1
2 0 2 0
2 1 1 0
Объяснение: 0 делится на три. 0 >> 1 + 0 = 0
. Повторяйте с помощью S = (S >> 1 + I) % 3
и O = 1
, если S == 0
.
S'
отличается от предыдущего, но O работает одинаково, поскольку S'
равно 0 для тех же случаев (00 и 11). Поскольку O одинаково в обоих случаях, O_LSB = O_MSB, поэтому, чтобы сделать MSB коротким, как LSB, или наоборот, просто используйте кратчайший из них.
Ответ 2
Существует довольно известный трюк для определения того, является ли число кратным 11, путем поочередного добавления и вычитания его десятичных цифр. Если число, которое вы получаете в конце, кратно 11, то число, с которого вы начали, также кратно 11:
47278 4 - 7 + 2 - 7 + 8 = 0, multiple of 11 (47278 = 11 * 4298)
52214 5 - 2 + 2 - 1 + 4 = 8, not multiple of 11 (52214 = 11 * 4746 + 8)
Мы можем применить тот же трюк к двоичным числам. Двоичное число является кратным 3 тогда и только тогда, когда переменная сумма его битов также кратно 3:
4 = 100 1 - 0 + 0 = 1, not multiple of 3
6 = 110 1 - 1 + 0 = 0, multiple of 3
78 = 1001110 1 - 0 + 0 - 1 + 1 - 1 + 0 = 0, multiple of 3
109 = 1101101 1 - 1 + 0 - 1 + 1 - 0 + 1 = 1, not multiple of 3
Не имеет значения, начинаете ли вы с MSB или LSB, поэтому следующая функция Python работает одинаково хорошо в обоих случаях. Он принимает итератор, который возвращает бит по одному. multiplier
чередуется между 1 и 2 вместо 1 и -1, чтобы не принимать по модулю отрицательное число.
def divisibleBy3(iterator):
multiplier = 1
accumulator = 0
for bit in iterator:
accumulator = (accumulator + bit * multiplier) % 3
multiplier = 3 - multiplier
return accumulator == 0
Ответ 3
Здесь... что-то новое... как проверить, если двоичное число любой длины (даже тысячи цифр) делится на 3.
alt text http://i25.tinypic.com/23oe41.png
-->((0))<---1--->()<---0--->(1) ASCII representation of graph
Из рисунка.
1) Вы начинаете в двойном круге.
2) Когда вы получаете один или ноль, если цифра находится внутри круга, вы остаетесь в этом круге. Однако, если цифра находится на линии, вы перемещаетесь по линии.
3) Повторите шаг два, пока все цифры не будут пересчитаны.
4) Если вы, наконец, попадаете в двойной круг, тогда двоичное число делится на 3.
Вы также можете использовать это для генерации чисел, делящихся на 3. И я бы не хотел, чтобы было сложно преобразовать это в схему.
1 пример с использованием графика...
11000000000001011111111111101 делится на 3 (снова заканчивается в двойном круге)
Попробуйте сами.
Вы также можете выполнять аналогичные трюки для выполнения MOD 10, поскольку при преобразовании двоичных чисел в номера базы 10. (10 кругов, каждый из которых удваивается, и они представляют значения от 0 до 9, полученные по модулю)
EDIT: это для цифр, идущих слева направо, но не трудно модифицировать конечный автомат, чтобы принять обратный язык.
ПРИМЕЧАНИЕ. В представлении ASCII графика() обозначает один круг, а (()) обозначает двойной круг. В машинах с конечным состоянием они называются состояниями, а двойной круг - условием принятия (состояние, которое означает, что он равномерно делится на 3)
Ответ 4
Вот простой способ сделать это вручную.
Поскольку 1 = 2 2 mod 3, мы получаем 1 = 2 2n mod 3 для каждого натурального числа.
Кроме того, 2 = 2 2n + 1 mod 3. Следовательно, можно определить, делится ли целое число на 3 путем подсчета 1 бита в позиции нечетного бита, умножьте это число на 2, добавьте количество 1- бит в четных позициях бит добавляют их к результату и проверяют, делится ли результат на 3.
Пример: 57 10= 111001 2.
Есть 2 бита в нечетных положениях и 2 бита в четных положениях. 2 * 2 + 2 = 6 делится на 3. Следовательно, 57 делится на 3.
Вот также мысль о решении вопроса c). Если инвертировать битовый порядок двоичного целого числа, то все биты остаются в четных/нечетных положениях или все биты изменяются. Следовательно, инвертирование порядка битов целочисленного n результатов является целым числом, которое делится на 3 тогда и только тогда, когда n делится на 3. Следовательно, любое решение для вопроса a) работает без изменений для вопроса b) и наоборот. Хм, может быть, это поможет выяснить, какой подход быстрее...
Ответ 5
Вам нужно делать все вычисления с использованием арифметического по модулю 3. Это способ
MSB:
number=0
while(!eof)
n=input()
number=(number *2 + n) mod 3
if(number == 0)
print divisible
LSB:
number = 0;
multiplier = 1;
while(!eof)
n=input()
number = (number + multiplier * n) mod 3
multiplier = (multiplier * 2) mod 3
if(number == 0)
print divisible
Это общая идея...
Теперь ваша роль состоит в понимании почему. Это правильно.
И да, сделайте домашнее задание самостоятельно;)
Ответ 6
Идея состоит в том, что число может увеличиваться сколь угодно долго, а это значит, что вы не можете использовать mod 3
здесь, так как ваш номер будет больше, чем емкость вашего целочисленного класса.
Идея состоит в том, чтобы заметить, что происходит с числом. Если вы добавляете биты вправо, то, что вы на самом деле делаете, сдвигается влево на один бит и добавляет новый бит.
Shift-left - это то же самое, что и умножение на 2, и добавление нового бита либо добавляет 0, либо 1. Предполагая, что мы начали с 0, мы можем сделать это рекурсивно, основываясь на модуле-3 последнего номера.
last | input || next | example
------------------------------------
0 | 0 || 0 | 0 * 2 + 0 = 0
0 | 1 || 1 | 0 * 2 + 1 = 1
1 | 0 || 2 | 1 * 2 + 0 = 2
1 | 1 || 0 | 1 * 2 + 1 = 0 (= 3 mod 3)
2 | 0 || 1 | 2 * 2 + 0 = 1 (= 4 mod 3)
2 | 1 || 2 | 2 * 2 + 1 = 2 (= 5 mod 3)
Теперь посмотрим, что произойдет, когда вы добавите бит влево. Во-первых, обратите внимание, что:
2 2n mod 3 = 1
и
2 2n + 1 mod 3 = 2
Итак, теперь нам нужно либо добавить 1 или 2 к моду, основываясь на том, что текущая итерация нечетная или четная.
last | n is even? | input || next | example
-------------------------------------------
d/c | don't care | 0 || last | last + 0*2^n = last
0 | yes | 1 || 0 | 0 + 1*2^n = 1 (= 2^n mod 3)
0 | no | 1 || 0 | 0 + 1*2^n = 2 (= 2^n mod 3)
1 | yes | 1 || 0 | 1 + 1*2^n = 2
1 | no | 1 || 0 | 1 + 1*2^n = 0 (= 3 mod 3)
1 | yes | 1 || 0 | 2 + 1*2^n = 0
1 | no | 1 || 0 | 2 + 1*2^n = 1
Ответ 7
Фактически, метод LSB фактически упростит это. В C:
Метод MSB:
/*
Returns 1 if divisble by 3, otherwise 0
Note: It is assumed 'input' format is valid
*/
int is_divisible_by_3_msb(char *input) {
unsigned value = 0;
char *p = input;
if (*p == '1') {
value &= 1;
}
p++;
while (*p) {
if (*p != ',') {
value <<= 1;
if (*p == '1') {
ret &= 1;
}
}
p++;
}
return (value % 3 == 0) ? 1 : 0;
}
Метод LSB:
/*
Returns 1 if divisble by 3, otherwise 0
Note: It is assumed 'input' format is valid
*/
int is_divisible_by_3_lsb(char *input) {
unsigned value = 0;
unsigned mask = 1;
char *p = input;
while (*p) {
if (*p != ',') {
if (*p == '1') {
value &= mask;
}
mask <<= 1;
}
p++;
}
return (value % 3 == 0) ? 1 : 0;
}
Лично я с трудом верю, что один из них будет существенно отличаться от другого.
Ответ 8
input "0": (0) output 1
inputs "1,0,0": (4) output 0
inputs "1,1,0,0": (6) output 1
не должен ли этот последний вход 12
, или я не понимаю вопрос?
Ответ 9
Я думаю, что Натан Феллман находится на правильном пути для части a и b (кроме b требуется дополнительная часть состояния: вам нужно отслеживать, будет ли ваша позиция разряда нечетной или даже).
Я думаю, что трюк для части C отрицает значение last
на каждом шаге. То есть 0 переходит в 0, 1 переходит в 2 и 2 переходит в 1.
Ответ 10
Число делится на 3, если сумма его цифр делится на 3.
Таким образом, вы можете добавить цифры и получить сумму:
- если сумма больше или равна 10, используйте тот же метод
- если он 3,6,9, то он делится
- если сумма отличается от 3,6,9, то она не делится