Проверьте, является ли число делимым на 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, то она не делится