Не просто математика

Разговоры на любые темы: вы можете обсудить здесь какой-либо сайт, найти единомышленников или просто пообщаться...
Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Не просто математика

Сообщение Хакер » 27.03.2009 (Пт) 14:32

Сначала пример.
Код: Выделить всё
in      out
1       1
2       8
3       3
4       6
5       2
6       7
7       4
8       5

Нужно найти закономерность между входными и выходными данными. Закономерность должна быть безусловной (никаких «если») на уровне «поменять что-то местами» или «инвертировать такой-то бит».

Вот это простой пример с простой закономерностью. Она заключается в следующем:
Представленные выше числа — номера некоторых элементов. Обычные люди привыкли начинать нумерацию с единицы, а мы как программисты переиначим нумерацию так, чтобы она начиналась с нуля:
Код: Выделить всё
in-1  in-0    out-0  out-1
1     0       0      1
2     1       7      8
3     2       2      3
4     3       5      6
5     4       1      2
6     5       6      7
7     6       3      4
8     7       4      5


Теперь у нас есть одно преимущество: 0-based индексы укладываются в 3 бита. Распишем (или иначе говоря: представим в двоичном виде):

Код: Выделить всё
in-1  in-0 in-bin out-bin  out-0  out-1
1     0    000    000      0      1
2     1    001    111      7      8
3     2    010    010      2      3
4     3    011    101      5      6
5     4    100    001      1      2
6     5    101    110      6      7
7     6    110    011      3      4
8     7    111    100      4      5


Тут уже можно кое-что увидеть. Для некоторых строек достаточным для преобразования входных данных в выходные было бы поменять местами биты. Давайте введём ещё колонку и пометим те строки, для которых это правило действует:

Код: Выделить всё
in-1  in-0 in-bin out-bin  out-0  out-1  swappable
1     0    000    000      0      1      Y
2     1    001    111      7      8      N
3     2    010    010      2      3      Y
4     3    011    101      5      6      N
5     4    100    001      1      2      Y
6     5    101    110      6      7      N
7     6    110    011      3      4      Y
8     7    111    100      4      5      N


Ага! Мы видим, что для нечетных строк перестановка бит работает, а для четных — нет. Но что нам может дать чётность/нечетность, если всё, что мы умеем делать это перестановки/реиндексации?

Отсортируем таблицу по первично последней графе и вторично по предпоследней:
Код: Выделить всё
in-1  in-0 in-bin out-bin  out-0  out-1  swappable
1     0    000    000      0      1      Y
5     4    100    001      1      2      Y
3     2    010    010      2      3      Y
7     6    110    011      3      4      Y
8     7    111    100      4      5      N
4     3    011    101      5      6      N
6     5    101    110      6      7      N
2     1    001    111      7      8      N

Ага, уже интересно! Простой перестановки битов будет достаточно если речь идёт о выходных данных в диапазоне 1—4. Для выходных данных 5—8 правило не работает.
Но посмотрим ещё чуть внимательнее на двоичное представлени последних 4 входов выходов. Внимательные заметят, что они тоже переставлены местами! in-bin на 5-ой строчке соответствут out-bin'у на 8-ой. in-bin на 6-ой строчке — out-bin'у на 7-ой. in-bin на 7-ой — out-bin'у на 6-ой.

Вобщем, последние 4 выходных варианта как бы «перекручены». А мы умеем менять что-нибудь местами. На этот раз поменяем местами нумерацию выходов по следующему правилу:
Код: Выделить всё
5 => 8
6 => 7
7 => 6
8 => 5


С учётом этого переиначивания выходных данных, обратимся к изначальным условиям:
Код: Выделить всё
in   new-out   out
1    1         1
2    5         8
3    3         3
4    7         6
5    2         2
6    6         7
7    4         4
8    8         5


Теперь перейдём на 0-based индексы:
Код: Выделить всё
in in-0 new-out-0  new-out   out
1  0    0          1         1
2  1    4          5         8
3  2    2          3         3
4  3    6          7         6
5  4    1          2         2
6  5    5          6         7
7  6    3          4         4
8  7    7          8         5


А теперь распишем in-0 и new-out-0 в двоичном виде:
Код: Выделить всё
in in-0 in-bin out-bin new-out-0  new-out   out
1  0    000    000     0          1         1
2  1    001    100     4          5         8
3  2    010    010     2          3         3
4  3    011    110     6          7         6
5  4    100    001     1          2         2
6  5    101    101     5          6         7
7  6    110    011     3          4         4
8  7    111    111     7          8         5

И что мы теперь видим :) ? Что зеркальное отражение битов теперь работает для всех строк, с учётом зеркального отражения выходов 5—8.
Всё, закономерность (безусловная), основанная на отзеркаливаниях обнаружена.

_______________

Это была учебная задача. А теперь боевая:
Код: Выделить всё
1 - 1           
2 - 3
3 - 2
4 - 4
5 - 5
6 - 6
7 - 7
8 - 8
9 - 11
10 - 12
11 - 9
12 - 10
13 - 15
14 - 16
15 - 13
16 - 14


Кроме cross-over-отзеркаливания можно делать слияние половин в шахм. порядке, например:
Код: Выделить всё
Отзеркаливание:
1 => 4
2 => 3
3 => 2
4 => 1

Слияние половин:
1 => 1
3 => 2
2 => 3
4 => 4

Композиция отзеркаливания и слияния:
1 => 1
4 => 2
3 => 3
2 => 4


Кстати, отзеркаливание, обычно делается либо полностью (как в случае со входами) либо, как и слияние, половинами.

Раскусит кто-нибудь? :)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Вернуться в Народный треп

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 49

    TopList