Страницы

Поиск по вопросам

Показаны сообщения с ярлыком forth. Показать все сообщения
Показаны сообщения с ярлыком forth. Показать все сообщения

пятница, 13 марта 2020 г.

Как сделать уникальные (неповторяющиеся) последовательности данных?

#алгоритм #forth


История вопроса: Однажды мне пришлось сделать последовательности из 4 элементов.
Таких последовательностей 4! т.е. 24 . Чтобы не писать 24 раза почти одинаковые последовательности,
я заставил некоторые из них "вращаться"

Итого на 4 эл-та вращение приходилось 6 раз:

24 0 DO
TURN-N

4 I =  IF 6 L-VAR@ 5 L-VAR@ 7 L-VAR@ 8 L-VAR@ PRIEM-OB THEN
8 I =  IF 6 L-VAR@ 8 L-VAR@ 5 L-VAR@ 7 L-VAR@ PRIEM-OB THEN
12 I = IF 7 L-VAR@ 5 L-VAR@ 8 L-VAR@ 6 L-VAR@ PRIEM-OB THEN
16 I = IF 7 L-VAR@ 6 L-VAR@ 5 L-VAR@ 8 L-VAR@ PRIEM-OB THEN
20 I = IF 8 L-VAR@ 7 L-VAR@ 5 L-VAR@ 6 L-VAR@ PRIEM-OB THEN

LOOP


Слово TURN-N занимается "вращением" ( 1234 -- 4123 )
L-VAR@ - РАЗЪИМЕНОВАТЬ ЛОК.ПЕРЕМЕННУЮ ПО АДРЕСУ

Как всё это дело автоматизировать? Чтобы не из 4-х элементов, а из 5-ти или 6-ти?
    


Ответы

Ответ 1



\ Генератор перестановок символов в строке от Garbler'a : cswap ( a1 a2 -- ) 2DUP 2>R C@ SWAP C@ R> C! R> C! ; : cnotfind ( c s2 s1 -- t/f ) 1 -ROT ?DO OVER I C@ = IF 0 AND LEAVE THEN LOOP SWAP DROP ; : variants ( 0 s2 s1 str len --> count s2 s1' str len ) 2>R 2DUP - 1 < IF 2>R 1+ 2R> ." > " 2R> 2DUP TYPE CR EXIT THEN DUP >R BEGIN 2DUP > WHILE DUP C@ OVER R@ cnotfind IF DUP R@ cswap R> 1+ SWAP 2R> ROT >R RECURSE R> -ROT 2>R SWAP 1- >R DUP R@ cswap THEN 1+ REPEAT DROP R> 2R> ; : VARIANTS ( asc # --> n ) DUP 0 = IF 2DROP 0 EXIT THEN 2DUP 2>R OVER + SWAP 0 -ROT 2R> variants 2DROP 2DROP ; \ Пример получения всех перестановок символов в строке S" 123456" 2DUP VARIANTS .( ] variants: ) . TYPE CR CR \ для чисел количеством до 256 можно использовать массив указателей на \ массив чисел а массив указателей подавать как строку на вход слова VARIANTS \ как в приведенном выше примере

Ответ 2



Общий подход Чтобы решить эту задачу элегантно в общем виде, следует разделить код, который генерирует перестановки, и код, который работает с каждой отдельной перестановкой. Конечно же, перестановки должны генерироваться автоматически. Элементы, подлежащие перестановке, обычно помещаются в список или массив. Генератор перестановок следует выделить в отдельный функциональный модуль, достойный включения в библиотеку :) Если задача разовая, и число элементов небольшое, то можно сгенерировать последовательность перестановок в текстовом виде каким-то из существующих инструментов, и автоматически преобразовать эту последовательность в код. Алгоритм генерации перестановок Классический рекурсивный алгоритм генерации всевозможных перестановок легко понять по индукции. Каждая перестановка — эта некоторая последовательность. Для множества из одного элемента — будет одна перестановка из этого элемента. Для множества из N элементов — мы по очереди берем каждый из этих элементов и объеденяем с перестановками оставшихся N-1 элементов. Пример. Для двух элементов {1,2} — берем 1 и объединяем с 2, берем 2 и объединяем с 1. Для трех элементов {1,2,3} — берем 1 и объединяем с перестановками для {2,3}, берем 2 и объединяем с перестановками для {1,3}, берем 3 и объединяем с перестновками для {1,2}. Иллюстрация кодом Для простоты примера, будем генерировать перестановки N верхних элементов стека, и после каждой перестановки выполнять заданное через xt слово; это слово должно оставить состояние стека без изменений. Код заточен под SP-Forth REQUIRE NDROP ~pinka/lib/ext/basics.f REQUIRE { lib/ext/locals.f : (FOR-PERMUTATION) ( i*x i xt -- i*x ) { i xt | j } i 1 = IF xt EXECUTE EXIT THEN i 1- TO j i 0 DO j xt RECURSE j ROLL \ 0-based numbering LOOP ; : FOR-PERMUTATION ( i*x i xt -- ) \ xt ( i*x -- i*x ) OVER 0 = IF 2DROP EXIT THEN OVER >R (FOR-PERMUTATION) R> NDROP ; Испытание : print-stack-state ( i*x -- i*x ) .S CR ; 3 2 1 3 ' print-stack-state FOR-PERMUTATION

понедельник, 23 декабря 2019 г.

Как удалить произвольный элемента стека Forth

#стек #forth


Как удалить произвольный элемент из стека данных в языке Форт?
    


Ответы

Ответ 1



N ROLL DROP где N — номер элемента от вершины стека начиная с 0. Например, фраза 4 3 2 1 0 3 ROLL DROP оставит на стеке 4 2 1 0. Такой вариант слова ROLL закреплен в спецификации начиная с Forth-83.

понедельник, 3 июня 2019 г.

Как сделать уникальные (неповторяющиеся) последовательности данных?

История вопроса: Однажды мне пришлось сделать последовательности из 4 элементов. Таких последовательностей 4! т.е. 24 . Чтобы не писать 24 раза почти одинаковые последовательности, я заставил некоторые из них "вращаться"
Итого на 4 эл-та вращение приходилось 6 раз:
24 0 DO TURN-N
4 I = IF 6 L-VAR@ 5 L-VAR@ 7 L-VAR@ 8 L-VAR@ PRIEM-OB THEN 8 I = IF 6 L-VAR@ 8 L-VAR@ 5 L-VAR@ 7 L-VAR@ PRIEM-OB THEN 12 I = IF 7 L-VAR@ 5 L-VAR@ 8 L-VAR@ 6 L-VAR@ PRIEM-OB THEN 16 I = IF 7 L-VAR@ 6 L-VAR@ 5 L-VAR@ 8 L-VAR@ PRIEM-OB THEN 20 I = IF 8 L-VAR@ 7 L-VAR@ 5 L-VAR@ 6 L-VAR@ PRIEM-OB THEN
LOOP

Слово TURN-N занимается "вращением" ( 1234 -- 4123 ) L-VAR@ - РАЗЪИМЕНОВАТЬ ЛОК.ПЕРЕМЕННУЮ ПО АДРЕСУ
Как всё это дело автоматизировать? Чтобы не из 4-х элементов, а из 5-ти или 6-ти?


Ответ

\ Генератор перестановок символов в строке от Garbler'a : cswap ( a1 a2 -- ) 2DUP 2>R C@ SWAP C@ R> C! R> C! ; : cnotfind ( c s2 s1 -- t/f ) 1 -ROT ?DO OVER I C@ = IF 0 AND LEAVE THEN LOOP SWAP DROP ; : variants ( 0 s2 s1 str len --> count s2 s1' str len ) 2>R 2DUP - 1 < IF 2>R 1+ 2R> ." > " 2R> 2DUP TYPE CR EXIT THEN DUP >R BEGIN 2DUP > WHILE DUP C@ OVER R@ cnotfind IF DUP R@ cswap R> 1+ SWAP 2R> ROT >R RECURSE R> -ROT 2>R SWAP 1- >R DUP R@ cswap THEN 1+ REPEAT DROP R> 2R> ; : VARIANTS ( asc # --> n ) DUP 0 = IF 2DROP 0 EXIT THEN 2DUP 2>R OVER + SWAP 0 -ROT 2R> variants 2DROP 2DROP ;
\ Пример получения всех перестановок символов в строке S" 123456" 2DUP VARIANTS .( ] variants: ) . TYPE CR CR
\ для чисел количеством до 256 можно использовать массив указателей на \ массив чисел а массив указателей подавать как строку на вход слова VARIANTS \ как в приведенном выше примере

среда, 21 ноября 2018 г.

Как удалить произвольный элемента стека Forth

Как удалить произвольный элемент из стека данных в языке Форт?


Ответ

N ROLL DROP
где N — номер элемента от вершины стека начиная с 0.
Например, фраза 4 3 2 1 0 3 ROLL DROP оставит на стеке 4 2 1 0
Такой вариант слова ROLL закреплен в спецификации начиная с Forth-83