Код кажется сложным и трудным для понимания на первый взгляд. Однако, если рассмотреть задачу в форме булевой алгебры, все становится ясно.
Что нам нужно сделать, так это сохранить количество 1's
каждого бита. Поскольку каждый из 32 битов подчиняется одним и тем же правилам, нам просто нужно рассмотреть 1 бит. Мы знаем, что число появляется не более 3 раз, поэтому нам нужно 2 бита для его хранения. Теперь у нас есть 4 состояния, 00, 01, 10 и 11, но нам нужно только 3 из них.
В вашем решении выбрано 01 для одного и 10 для двоих. Пусть one
представляет первый бит, two
представляет второй бит. Затем нам нужно установить правила для one_
и two_
, чтобы они действовали так, как мы надеемся. Полный цикл: 00->10->01->00(0->1->2->3/0).
Лучше сделать карту Карно, также известную как K-map. Для карты Карно Ref.
счетчик с 3 состояниями
Соответствующие значения A[i]
, two
, one
и two_
, one_
после
0 0 0 | 0 0
0 0 1 | 0 1
0 1 0 | 1 0
0 1 1 | X X
1 0 0 | 0 1
1 0 1 | 1 0
1 1 0 | 0 0
1 1 1 | X X
Здесь X означает, что нас не волнует этот случай или просто конечное значение двух и одного, где бы их вывод ни был 1, это также можно учитывать, результат будет одинаковым и для 4-го, и для 8-го случай не будет для него существовать, так как два и один не может быть одним одновременно.
Если вы думаете, как я придумал приведенную выше таблицу. Я собираюсь объяснить один из них. Рассматривая 7-й случай, когда A[i] равно 1, два равно 1, т.е. уже существует A[i], которое повторяется два раза. Наконец, есть 3 A[i]. Так как их 3, то two_
и one_
оба должны сбрасываться на 0.
С учетом one_
значение равно 1 для двух случаев, т. е. 2-го и 5-го. Принятие 1 аналогично рассмотрению minterms в K-map.
one_ = (~A[i] & ~two & one) | (A[i] & ~two & ~one)
Если ~two
взять обычное, то
(~A[i] & one) | (A[i] & ~one) will be same as (A[i]^one)
Затем,
one_ = (one ^ A[i]) & ~two
С учетом two_
значение равно 1 для двух случаев, т. е. 3-го и 6-го. Принятие 1 аналогично рассмотрению minterms в K-map.
two_ = (~A[i] & two & ~one) | (A[i] & ~two & one)
Манипуляции с битами для рассчитанного two_ помогут решить проблему. Но, как вы упомянули
two_ = (A[i] & one) | (~A[i] & two)
Приведенное выше выражение можно легко получить, используя K-map
, учитывая, что не имеет значения, то есть X для всех случаев, упомянутых выше, так как рассмотрение X не повлияет наше решение.
С учетом two_
и с учетом X
Это значение равно 1 для двух случаев, т. е. 3-го и 6-го, и X для двух случаев, т. е. 4-го и 8-й случай. Теперь рассмотрим minterms.
two_ = (~A[i] & two & ~one) | (A[i] & ~two & one) | (~A[i] & two & one) | (A[i] & two & one)
Теперь, взяв общие (A и один) и (~A и два) в приведенном выше выражении, вы получите (два | ~ два) и (один | ~ один), что равно 1. Итак, мы будем остался с
two_ = (A[i] & one) | (~A[i] & two)
Для получения дополнительной информации!
22.01.2020