:- use_module( library( lists) ) .
% ----------------------------
% задание 1: шелл (седжвик)
% ----------------------------
% shs(+l, -s, -other_list)
shs( L, S, OtherList) :-
length( L, N) ,
sg( N, Gs) ,
sp( Gs, L, S) ,
generate_other_list( N, OtherList) . % Создаем SomeOtherList
% sg(+n, -gs)
sg( N, Gs) :-
( N =< 1 - > Gs = [ 1 ]
; sgk( N, 0 , [ ] , Rs) ,
reverse( Rs, Gs)
) .
sgk( N, K, A, Rs) :-
hk( K, H) ,
hk( K1, H1) ,
( 3 * H1 > N - >
Rs = [ H| A]
; sgk( N, K1, [ H| A] , Rs)
) .
% hk(+k,-h)
hk( K, H) :-
) .
sp( [ ] , L, L) .
sp( [ G| Gs] , L, S) :-
gp( G, L, L1) ,
sp( Gs, L1, S) .
% gp(+g,+l,-s)
gp( G, L, S) :-
en( L, 0 , Ps) ,
findall ( Ns
, ( between
( 0 , G1
, R
) , cls
( Ps
, G
, R
, Ns
) ) , Bs
) , append( Bs, All) ,
keysort( All, Ss) ,
vs( Ss, S) .
cls( Ps, G, R, Ns) :-
iv( Cs, Vs1, Is1) ,
ins( Vs1, Vs2) ,
pi( Is1, Vs2, Ns) .
pr
( G
, R
, I
- _
) :- 0 is ( I
- R
) mod G
.
en( [ ] , _, [ ] ) .
en( [ X| Xs] , I, [ I- X| Ps] ) :-
en( Xs, I1, Ps) .
iv( [ ] , [ ] , [ ] ) .
iv
( [ I
- V
| T
] , [ V
| Vs
] , [ I
| Is ] ) :- iv
( T
, Vs
, Is ) .
pi( [ ] , [ ] , [ ] ) .
pi
( [ I
| Is ] , [ V
| Vs
] , [ I
- V
| T
] ) :- pi
( Is , Vs
, T
) .
vs( [ ] , [ ] ) .
vs( [ _- V| T] , [ V| Vs] ) :- vs( T, Vs) .
% ins(+l,-s)
ins( [ ] , [ ] ) .
ins( [ X| Xs] , S) :- ins( Xs, S1) , is1( X, S1, S) .
is1( X, [ ] , [ X] ) .
is1( X, [ Y| Ys] , [ X, Y| Ys] ) :- X =< Y, ! .
is1( X, [ Y| Ys] , [ Y| Zs] ) :- is1( X, Ys, Zs) .
% Оценка сложности сортировки Шелла (Sedgewick's sequence): O(N^(4/3)) в среднем, до O(N^(3/2)) в худшем случае
shellsort_complexity( N, Complexity) :-
Complexity
is N
** ( 4 / 3 ) . % Средняя сложность
% Пример использования сортировки Шелла
ex_shs :-
L = [ 3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 ] ,
shs( L, S, OtherList) ,
length( L, N) ,
shellsort_complexity( N, Complexity) ,
format( 'Сортировка Шелла:~n' ) ,
format( ' Исходный список: ~w~n' , [ L] ) ,
format( ' Отсортированный список: ~w~n' , [ S] ) ,
format( ' Другой список: ~w~n' , [ OtherList] ) , % Выводим второй список
format( ' Оценка сложности (O(N^(4/3))): ~w для N = ~w~n' , [ Complexity, N] ) .
% ----------------------------
% задание 2: бинарные включения
% ----------------------------
% bis(+l,-s, -other_list)
bis( L, S, OtherList) :- bis1( L, [ ] , S) , generate_other_list( N, OtherList) , length( L, N) .
bis1( [ ] , A, A) .
bis1( [ X| Xs] , A, S) :-
bin_ins( X, A, A1) ,
bis1( Xs, A1, S) .
% bin_ins(+x,+l,-r)
bin_ins( X, L, R) :-
length( L, N) ,
bin_pos( X, L, 0 , N, P) ,
sp2( P, L, A, B) ,
append( A, [ X| B] , R) .
% bin_pos(+x,+l,+lo,+hi,-p)
bin_pos( X, L, Lo, Hi, P) :-
( Lo >= Hi - >
P = Lo
nth0( M, L, V) ,
( X =< V - >
bin_pos( X, L, Lo, M, P)
bin_pos( X, L, M1, Hi, P)
)
) .
% sp2(+k,+l,-a,-b)
sp2( 0 , L, [ ] , L) :- ! .
sp2( K, [ X| Xs] , [ X| A] , B) :-
K > 0 ,
sp2( K1, Xs, A, B) .
% Оценка сложности бинарной вставки: O(N^2) в худшем случае
binary_insertion_complexity( N, Complexity) :-
Complexity
is N
* N
. % Или N * log(N) для среднего случая
% Пример использования бинарных включений
ex_bis :-
L = [ 3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 ] ,
bis( L, S, OtherList) ,
length( L, N) ,
binary_insertion_complexity( N, Complexity) ,
format( 'Бинарные включения:~n' ) ,
format( ' Исходный список: ~w~n' , [ L] ) ,
format( ' Отсортированный список: ~w~n' , [ S] ) ,
format( ' Другой список: ~w~n' , [ OtherList] ) , % выводим второй список
format( ' Оценка сложности (O(N^2)): ~w для N = ~w~n' , [ Complexity, N] ) .
% ----------------------------
% задание 3: "слово из домино" (игра)
% ----------------------------
% igra(-w)
igra( w( I, G, R, A) ) :-
ds( Ts) ,
gr( Ts, 7 , 42 , Ti, T1) , ch( Ti, I) ,
gr( T1, 7 , 42 , Tg, T2) , ch( Tg, G) ,
gr( T2, 7 , 42 , Tr, T3) , ch( Tr, R) ,
T3 = Ta, sm( Ta, 42 ) , ch( Ta, A) .
% ds(-ts)
ds
( Ts
) :- findall ( A
- B
, ( between
( 0 , 6 , A
) , between
( A
, 6 , B
) ) , Ts
) .
% sm(+ts,-s)
sm( [ ] , 0 ) .
sm( [ A- B| T] , S) :-
sm( T, S1) ,
% gr(+ts,+k,+s,-g,-r)
gr( Ts, 0 , 0 , [ ] , Ts) :- ! .
gr( Ts, K, S, [ X| G] , R) :-
K > 0 , S >= 0 ,
select( X, Ts, T1) ,
X = A- B,
gr( T1, K1, S1, G, R) .
% ch(+ts,-c)
ch( Ts, C) :-
select( T, Ts, R) ,
or( T, A- B) ,
ch1( R, B, [ A- B] , C) .
ch1( [ ] , _, A, C) :- reverse( A, C) .
ch1( Ts, X, A, C) :-
select( T, Ts, R) ,
or1( T, X- Y) ,
ch1( R, Y, [ X- Y| A] , C) .
or( A- B, A- B) .
or( A- B, B- A) .
or1( A- B, X- Y) :- ( X= A, Y= B ; X= B, Y= A) .
% Пример использования игры в домино
ex_igra :-
igra( W) ,
format( 'Игра "Слово из домино":~n' ) ,
format( ' Решение: ~w~n' , [ W] ) .
% ----------------------------
% задание 4 (вариант 2): вставка подсписка с i-го элемента
% ----------------------------
% ins_sub(+sub,+l,+i,-r)
ins_sub( Sub, L, I, R) :-
I >= 1 ,
sp2( K, L, P, S) ,
append( P, Sub, T) ,
append( T, S, R) .
% Пример использования вставки подсписка
ex_ins_sub :-
Sub = [ 7 , 8 , 9 ] ,
L = [ 1 , 2 , 3 , 4 , 5 , 6 ] ,
I = 3 ,
ins_sub( Sub, L, I, R) ,
format( 'Вставка подсписка:~n' ) ,
format( ' Исходный список: ~w~n' , [ L] ) ,
format( ' Подсписок: ~w~n' , [ Sub] ) ,
format( ' Индекс вставки: ~w~n' , [ I] ) ,
format( ' Результат: ~w~n' , [ R] ) .
% Вспомогательное правило для генерации второго списка
generate_other_list( N, OtherList) :-
findall ( X
, ( between
( 1 , N
, I
) , X
is I
* 3 ) , OtherList
) . % Другой список кратный трем
% Запуск всех примеров
run_examples :-
ex_shs,
ex_bis,
ex_igra,
ex_ins_sub.
?- run_examples.
Oi0gdXNlX21vZHVsZShsaWJyYXJ5KGxpc3RzKSkuCgolIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KJSDQt9Cw0LTQsNC90LjQtSAxOiDRiNC10LvQuyAo0YHQtdC00LbQstC40LopCiUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKJSBzaHMoK2wsIC1zLCAtb3RoZXJfbGlzdCkKc2hzKEwsIFMsIE90aGVyTGlzdCkgOi0KICAgIGxlbmd0aChMLCBOKSwKICAgIHNnKE4sIEdzKSwKICAgIHNwKEdzLCBMLCBTKSwKICAgIGdlbmVyYXRlX290aGVyX2xpc3QoTiwgT3RoZXJMaXN0KS4gICUg0KHQvtC30LTQsNC10LwgU29tZU90aGVyTGlzdAoKJSBzZygrbiwgLWdzKQpzZyhOLCBHcykgOi0KICAgICggTiA9PCAxIC0+IEdzID0gWzFdCiAgICA7IHNnayhOLCAwLCBbXSwgUnMpLAogICAgICByZXZlcnNlKFJzLCBHcykKICAgICkuCgpzZ2soTiwgSywgQSwgUnMpIDotCiAgICBoayhLLCBIKSwKICAgIEsxIGlzIEsgKyAxLAogICAgaGsoSzEsIEgxKSwKICAgICggMypIMSA+IE4gLT4KICAgICAgICBScyA9IFtIfEFdCiAgICA7ICAgc2drKE4sIEsxLCBbSHxBXSwgUnMpCiAgICApLgoKJSBoaygraywtaCkKaGsoSywgSCkgOi0KICAgICggMCBpcyBLIG1vZCAyIC0+CiAgICAgICAgUDJrICBpcyAxIDw8IEssCiAgICAgICAgSzIgICBpcyBLIC8vIDIsCiAgICAgICAgUDJrMiBpcyAxIDw8IEsyLAogICAgICAgIEggaXMgOSpQMmsgLSA5KlAyazIgKyAxCiAgICA7ICAgUDJrICBpcyAxIDw8IEssCiAgICAgICAgSzIgICBpcyAoSyArIDEpIC8vIDIsCiAgICAgICAgUDJrMiBpcyAxIDw8IEsyLAogICAgICAgIEggaXMgOCpQMmsgLSA2KlAyazIgKyAxCiAgICApLgoKc3AoW10sIEwsIEwpLgpzcChbR3xHc10sIEwsIFMpIDotCiAgICBncChHLCBMLCBMMSksCiAgICBzcChHcywgTDEsIFMpLgoKJSBncCgrZywrbCwtcykKZ3AoRywgTCwgUykgOi0KICAgIGVuKEwsIDAsIFBzKSwKICAgIEcxIGlzIEcgLSAxLAogICAgZmluZGFsbChOcywgKGJldHdlZW4oMCwgRzEsIFIpLCBjbHMoUHMsIEcsIFIsIE5zKSksIEJzKSwKICAgIGFwcGVuZChCcywgQWxsKSwKICAgIGtleXNvcnQoQWxsLCBTcyksCiAgICB2cyhTcywgUykuCgpjbHMoUHMsIEcsIFIsIE5zKSA6LQogICAgaW5jbHVkZShwcihHLCBSKSwgUHMsIENzKSwKICAgIGl2KENzLCBWczEsIElzMSksCiAgICBpbnMoVnMxLCBWczIpLAogICAgcGkoSXMxLCBWczIsIE5zKS4KCnByKEcsIFIsIEktXykgOi0gMCBpcyAoSSAtIFIpIG1vZCBHLgoKZW4oW10sIF8sIFtdKS4KZW4oW1h8WHNdLCBJLCBbSS1YfFBzXSkgOi0KICAgIEkxIGlzIEkgKyAxLAogICAgZW4oWHMsIEkxLCBQcykuCgppdihbXSwgW10sIFtdKS4KaXYoW0ktVnxUXSwgW1Z8VnNdLCBbSXxJc10pIDotIGl2KFQsIFZzLCBJcykuCgpwaShbXSwgW10sIFtdKS4KcGkoW0l8SXNdLCBbVnxWc10sIFtJLVZ8VF0pIDotIHBpKElzLCBWcywgVCkuCgp2cyhbXSwgW10pLgp2cyhbXy1WfFRdLCBbVnxWc10pIDotIHZzKFQsIFZzKS4KCiUgaW5zKCtsLC1zKQppbnMoW10sIFtdKS4KaW5zKFtYfFhzXSwgUykgOi0gaW5zKFhzLCBTMSksIGlzMShYLCBTMSwgUykuCgppczEoWCwgW10sIFtYXSkuCmlzMShYLCBbWXxZc10sIFtYLFl8WXNdKSA6LSBYID08IFksICEuCmlzMShYLCBbWXxZc10sIFtZfFpzXSkgOi0gaXMxKFgsIFlzLCBacykuCgolINCe0YbQtdC90LrQsCDRgdC70L7QttC90L7RgdGC0Lgg0YHQvtGA0YLQuNGA0L7QstC60Lgg0KjQtdC70LvQsCAoU2VkZ2V3aWNrJ3Mgc2VxdWVuY2UpOiBPKE5eKDQvMykpINCyINGB0YDQtdC00L3QtdC8LCDQtNC+IE8oTl4oMy8yKSkgINCyINGF0YPQtNGI0LXQvCDRgdC70YPRh9Cw0LUKc2hlbGxzb3J0X2NvbXBsZXhpdHkoTiwgQ29tcGxleGl0eSkgOi0KICAgIENvbXBsZXhpdHkgaXMgTioqKDQvMykuICAlINCh0YDQtdC00L3Rj9GPINGB0LvQvtC20L3QvtGB0YLRjAoKJSDQn9GA0LjQvNC10YAg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC40Y8g0YHQvtGA0YLQuNGA0L7QstC60Lgg0KjQtdC70LvQsApleF9zaHMgOi0KICAgIEwgPSBbMywgMSwgNCwgMSwgNSwgOSwgMiwgNiwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3LCAxOCwgMTksIDIwLCAyMV0sCiAgICBzaHMoTCwgUywgT3RoZXJMaXN0KSwKICAgIGxlbmd0aChMLCBOKSwKICAgIHNoZWxsc29ydF9jb21wbGV4aXR5KE4sIENvbXBsZXhpdHkpLAogICAgZm9ybWF0KCfQodC+0YDRgtC40YDQvtCy0LrQsCDQqNC10LvQu9CwOn5uJyksCiAgICBmb3JtYXQoJyAg0JjRgdGF0L7QtNC90YvQuSDRgdC/0LjRgdC+0Lo6IH53fm4nLCBbTF0pLAogICAgZm9ybWF0KCcgINCe0YLRgdC+0YDRgtC40YDQvtCy0LDQvdC90YvQuSDRgdC/0LjRgdC+0Lo6IH53fm4nLCBbU10pLAogICAgZm9ybWF0KCcgINCU0YDRg9Cz0L7QuSDRgdC/0LjRgdC+0Lo6IH53fm4nLCBbT3RoZXJMaXN0XSksICUg0JLRi9Cy0L7QtNC40Lwg0LLRgtC+0YDQvtC5INGB0L/QuNGB0L7QugogICAgZm9ybWF0KCcgINCe0YbQtdC90LrQsCDRgdC70L7QttC90L7RgdGC0LggKE8oTl4oNC8zKSkpOiB+dyDQtNC70Y8gTiA9IH53fm4nLCBbQ29tcGxleGl0eSwgTl0pLgoKCiUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQolINC30LDQtNCw0L3QuNC1IDI6INCx0LjQvdCw0YDQvdGL0LUg0LLQutC70Y7Rh9C10L3QuNGPCiUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKJSBiaXMoK2wsLXMsIC1vdGhlcl9saXN0KQpiaXMoTCwgUywgT3RoZXJMaXN0KSA6LSBiaXMxKEwsIFtdLCBTKSwgZ2VuZXJhdGVfb3RoZXJfbGlzdChOLCBPdGhlckxpc3QpLCBsZW5ndGgoTCwgTikuCgpiaXMxKFtdLCBBLCBBKS4KYmlzMShbWHxYc10sIEEsIFMpIDotCiAgICBiaW5faW5zKFgsIEEsIEExKSwKICAgIGJpczEoWHMsIEExLCBTKS4KCiUgYmluX2lucygreCwrbCwtcikKYmluX2lucyhYLCBMLCBSKSA6LQogICAgbGVuZ3RoKEwsIE4pLAogICAgYmluX3BvcyhYLCBMLCAwLCBOLCBQKSwKICAgIHNwMihQLCBMLCBBLCBCKSwKICAgIGFwcGVuZChBLCBbWHxCXSwgUikuCgolIGJpbl9wb3MoK3gsK2wsK2xvLCtoaSwtcCkKYmluX3BvcyhYLCBMLCBMbywgSGksIFApIDotCiAgICAoIExvID49IEhpIC0+CiAgICAgICAgUCA9IExvCiAgICA7IE0gaXMgKExvICsgSGkpIC8vIDIsCiAgICAgIG50aDAoTSwgTCwgViksCiAgICAgICggWCA9PCBWIC0+CiAgICAgICAgICBiaW5fcG9zKFgsIEwsIExvLCBNLCBQKQogICAgICA7IE0xIGlzIE0gKyAxLAogICAgICAgIGJpbl9wb3MoWCwgTCwgTTEsIEhpLCBQKQogICAgICApCiAgICApLgoKJSBzcDIoK2ssK2wsLWEsLWIpCnNwMigwLCBMLCBbXSwgTCkgOi0gIS4Kc3AyKEssIFtYfFhzXSwgW1h8QV0sIEIpIDotCiAgICBLID4gMCwKICAgIEsxIGlzIEsgLSAxLAogICAgc3AyKEsxLCBYcywgQSwgQikuCgolINCe0YbQtdC90LrQsCDRgdC70L7QttC90L7RgdGC0Lgg0LHQuNC90LDRgNC90L7QuSDQstGB0YLQsNCy0LrQuDogTyhOXjIpINCyINGF0YPQtNGI0LXQvCDRgdC70YPRh9Cw0LUKYmluYXJ5X2luc2VydGlvbl9jb21wbGV4aXR5KE4sIENvbXBsZXhpdHkpIDotCiAgICBDb21wbGV4aXR5IGlzIE4qTi4gICUg0JjQu9C4IE4gKiBsb2coTikg0LTQu9GPINGB0YDQtdC00L3QtdCz0L4g0YHQu9GD0YfQsNGPCgolINCf0YDQuNC80LXRgCDQuNGB0L/QvtC70YzQt9C+0LLQsNC90LjRjyDQsdC40L3QsNGA0L3Ri9GFINCy0LrQu9GO0YfQtdC90LjQuQpleF9iaXMgOi0KICAgIEwgPSBbMywgMSwgNCwgMSwgNSwgOSwgMiwgNiwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3LCAxOCwgMTksIDIwLCAyMV0sCiAgICBiaXMoTCwgUywgT3RoZXJMaXN0KSwKICAgIGxlbmd0aChMLCBOKSwKICAgIGJpbmFyeV9pbnNlcnRpb25fY29tcGxleGl0eShOLCBDb21wbGV4aXR5KSwKICAgIGZvcm1hdCgn0JHQuNC90LDRgNC90YvQtSDQstC60LvRjtGH0LXQvdC40Y86fm4nKSwKICAgIGZvcm1hdCgnICDQmNGB0YXQvtC00L3Ri9C5INGB0L/QuNGB0L7Qujogfnd+bicsIFtMXSksCiAgICBmb3JtYXQoJyAg0J7RgtGB0L7RgNGC0LjRgNC+0LLQsNC90L3Ri9C5INGB0L/QuNGB0L7Qujogfnd+bicsIFtTXSksCiAgICBmb3JtYXQoJyAg0JTRgNGD0LPQvtC5INGB0L/QuNGB0L7Qujogfnd+bicsIFtPdGhlckxpc3RdKSwgICUg0LLRi9Cy0L7QtNC40Lwg0LLRgtC+0YDQvtC5INGB0L/QuNGB0L7QugogICAgZm9ybWF0KCcgINCe0YbQtdC90LrQsCDRgdC70L7QttC90L7RgdGC0LggKE8oTl4yKSk6IH53INC00LvRjyBOID0gfnd+bicsIFtDb21wbGV4aXR5LCBOXSkuCgolIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KJSDQt9Cw0LTQsNC90LjQtSAzOiAi0YHQu9C+0LLQviDQuNC3INC00L7QvNC40L3QviIgKNC40LPRgNCwKQolIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiUgaWdyYSgtdykKaWdyYSh3KEksIEcsIFIsIEEpKSA6LQogICAgZHMoVHMpLAogICAgZ3IoVHMsIDcsIDQyLCBUaSwgVDEpLCBjaChUaSwgSSksCiAgICBncihUMSwgNywgNDIsIFRnLCBUMiksIGNoKFRnLCBHKSwKICAgIGdyKFQyLCA3LCA0MiwgVHIsIFQzKSwgY2goVHIsIFIpLAogICAgVDMgPSBUYSwgc20oVGEsIDQyKSwgY2goVGEsIEEpLgoKJSBkcygtdHMpCmRzKFRzKSA6LSBmaW5kYWxsKEEtQiwgKGJldHdlZW4oMCw2LEEpLCBiZXR3ZWVuKEEsNixCKSksIFRzKS4KCiUgc20oK3RzLC1zKQpzbShbXSwgMCkuCnNtKFtBLUJ8VF0sIFMpIDotCiAgICBzbShULCBTMSksCiAgICBTIGlzIFMxICsgQSArIEIuCgolIGdyKCt0cywraywrcywtZywtcikKZ3IoVHMsIDAsIDAsIFtdLCBUcykgOi0gIS4KZ3IoVHMsIEssIFMsIFtYfEddLCBSKSA6LQogICAgSyA+IDAsIFMgPj0gMCwKICAgIHNlbGVjdChYLCBUcywgVDEpLAogICAgWCA9IEEtQiwKICAgIFMxIGlzIFMgLSAoQSArIEIpLAogICAgSzEgaXMgSyAtIDEsCiAgICBncihUMSwgSzEsIFMxLCBHLCBSKS4KCiUgY2goK3RzLC1jKQpjaChUcywgQykgOi0KICAgIHNlbGVjdChULCBUcywgUiksCiAgICBvcihULCBBLUIpLAogICAgY2gxKFIsIEIsIFtBLUJdLCBDKS4KCmNoMShbXSwgXywgQSwgQykgOi0gcmV2ZXJzZShBLCBDKS4KY2gxKFRzLCBYLCBBLCBDKSA6LQogICAgc2VsZWN0KFQsIFRzLCBSKSwKICAgIG9yMShULCBYLVkpLAogICAgY2gxKFIsIFksIFtYLVl8QV0sIEMpLgoKb3IoQS1CLCBBLUIpLgpvcihBLUIsIEItQSkuCgpvcjEoQS1CLCBYLVkpIDotIChYPUEsIFk9QiA7IFg9QiwgWT1BKS4KCiUg0J/RgNC40LzQtdGAINC40YHQv9C+0LvRjNC30L7QstCw0L3QuNGPINC40LPRgNGLINCyINC00L7QvNC40L3QvgpleF9pZ3JhIDotCiAgICBpZ3JhKFcpLAogICAgZm9ybWF0KCfQmNCz0YDQsCAi0KHQu9C+0LLQviDQuNC3INC00L7QvNC40L3QviI6fm4nKSwKICAgIGZvcm1hdCgnICDQoNC10YjQtdC90LjQtTogfnd+bicsIFtXXSkuCgolIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KJSDQt9Cw0LTQsNC90LjQtSA0ICjQstCw0YDQuNCw0L3RgiAyKTog0LLRgdGC0LDQstC60LAg0L/QvtC00YHQv9C40YHQutCwINGBIGkt0LPQviDRjdC70LXQvNC10L3RgtCwCiUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKJSBpbnNfc3ViKCtzdWIsK2wsK2ksLXIpCmluc19zdWIoU3ViLCBMLCBJLCBSKSA6LQogICAgSSA+PSAxLAogICAgSyBpcyBJIC0gMSwKICAgIHNwMihLLCBMLCBQLCBTKSwKICAgIGFwcGVuZChQLCBTdWIsIFQpLAogICAgYXBwZW5kKFQsIFMsIFIpLgoKJSDQn9GA0LjQvNC10YAg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC40Y8g0LLRgdGC0LDQstC60Lgg0L/QvtC00YHQv9C40YHQutCwCmV4X2luc19zdWIgOi0KICAgIFN1YiA9IFs3LCA4LCA5XSwKICAgIEwgPSBbMSwgMiwgMywgNCwgNSwgNl0sCiAgICBJID0gMywKICAgIGluc19zdWIoU3ViLCBMLCBJLCBSKSwKICAgIGZvcm1hdCgn0JLRgdGC0LDQstC60LAg0L/QvtC00YHQv9C40YHQutCwOn5uJyksCiAgICBmb3JtYXQoJyAg0JjRgdGF0L7QtNC90YvQuSDRgdC/0LjRgdC+0Lo6IH53fm4nLCBbTF0pLAogICAgZm9ybWF0KCcgINCf0L7QtNGB0L/QuNGB0L7Qujogfnd+bicsIFtTdWJdKSwKICAgIGZvcm1hdCgnICDQmNC90LTQtdC60YEg0LLRgdGC0LDQstC60Lg6IH53fm4nLCBbSV0pLAogICAgZm9ybWF0KCcgINCg0LXQt9GD0LvRjNGC0LDRgjogfnd+bicsIFtSXSkuCgolINCS0YHQv9C+0LzQvtCz0LDRgtC10LvRjNC90L7QtSDQv9GA0LDQstC40LvQviDQtNC70Y8g0LPQtdC90LXRgNCw0YbQuNC4INCy0YLQvtGA0L7Qs9C+INGB0L/QuNGB0LrQsApnZW5lcmF0ZV9vdGhlcl9saXN0KE4sIE90aGVyTGlzdCkgOi0KICBmaW5kYWxsKFgsIChiZXR3ZWVuKDEsIE4sIEkpLCBYIGlzIEkgKiAzKSwgT3RoZXJMaXN0KS4gJSDQlNGA0YPQs9C+0Lkg0YHQv9C40YHQvtC6INC60YDQsNGC0L3Ri9C5INGC0YDQtdC8CgolINCX0LDQv9GD0YHQuiDQstGB0LXRhSDQv9GA0LjQvNC10YDQvtCyCnJ1bl9leGFtcGxlcyA6LQogICAgZXhfc2hzLAogICAgZXhfYmlzLAogICAgZXhfaWdyYSwKICAgIGV4X2luc19zdWIuCgogICAgPy0gcnVuX2V4YW1wbGVzLg==