Принцип «Голуб» та код «Гольф»


26

Принцип голуби говорить, що

Якщо N елементів розміщено в M полях з N > M , принаймні один ящик повинен містити більше одного елемента.

Для багатьох цей принцип має особливий статус порівняно з іншими математичними умовами. Як писав EW Dijkstra ,

Він оточений деякою містикою. Докази, які використовують його, часто розглядають як щось особливе, щось особливо геніальне.

Змагання

Мета цього виклику - проілюструвати принцип голубиної дуги за допомогою арт-репрезентацій ASCII. Конкретно:

  1. Візьміть як вхідні дані N(кількість предметів) і M(кількість коробок) з Nнегативними та Mпозитивними. Nможе бути меншим, ніж M(навіть якщо принцип не застосовується в такому випадку).
  2. Випадково виберіть одне з можливих призначень елементів до полів. Кожне завдання повинно мати ненульову ймовірність обрання.
  3. Створіть ASCII художнє представлення завдання таким чином:

    • Є Mрядки, кожна відповідна коробці.
    • Кожен рядок починається з символів, що не містять пробілів, таких як |.
    • Слідом за цим символом - ще один непробільний символ, наприклад #, повторюваний стільки разів, скільки є пункти в цьому полі.

Розглянемо, наприклад N = 8, M = 5. Якщо обрана розпаювання елементів для ящиків 4, 1, 0, 3, 0, то уявлення

|####
|#
|
|###
|

Різна пробіжка (в результаті чого інше призначення) тієї ж програми може дати

|#
|##
|#
|#
|###

Існує деяка гнучкість щодо представництва; Дивись нижче.

Конкретні правила

Код повинен теоретично працювати при будь-яких значеннях в Nі M. На практиці це може бути обмежено розміром пам'яті або типом даних.

Оскільки спостереження за результатами недостатньо для того, щоб визначити, чи всі призначення мають ненульову ймовірність , кожне подання повинно пояснити, яким кодом це досягається, якщо не очевидно.

Допускаються такі варіанти представлення:

  • Можна вибрати будь-яку пару різних, непробільних символів. Вони повинні бути послідовними для виконання програм.
  • 90-градусні обертання подання є прийнятними. Знову ж, вибір повинен бути послідовним.
  • Допускається проходження або пробіл пробілів.

Як приклад з іншим форматом представлення, наприклад N = 15, M = 6можуть бути результати двох виконання програми

VVVVVV
@@@@@@
@@ @@@
 @  @@
    @

або

VVVVV
@@@ @
@@@ @
@ @ @
@ @ @
@

Крім того, N = 5, M = 7може дати, використовуючи інший варіант подання,

  *
* * * *
UUUUUUU

або

 *** **
UUUUUUU

або

   *
*  *
*  * 
UUUUUUU

Зауважте, як принцип не застосовується в цьому випадку, оскільки N< M.

Загальні правила

Програми або функції дозволені на будь- якій мові програмування . Стандартні лазівки заборонені.

Введення можна взяти будь-якими розумними засобами ; і з будь-яким форматом, таким як масив з двох чисел або двох різних рядків.

Вихідні засоби та формат також гнучкі. Наприклад, результатом може бути список рядків або рядок з новими рядками; повертається як аргумент виводу функції або відображається в STDOUT. В останньому випадку не варто турбуватися про обертання рядків, викликане обмеженою шириною дисплея.

Найкоротший код у байтах виграє.


11
Насправді мені було потрібно до цього титулу ...
Мартін Ендер

@MartinEnder Це те, що "принцип голуба" має більше символів, ніж "кодовий гольф", чи є якийсь інший жарт?
сніданок хоче, щоб Моніка повернулася

5
@dorukayhan У звичайному браузері подивіться на текст трохи вище назви питання ...
Луїс Мендо

Відповіді:


2

Желе , 9 8 байт

=þṗX¥S⁵*

Це діадійна ланка, яка приймає М як лівий, а N - як аргумент правого. Вихід - це масив цілих чисел, де 0 являє собою голубів, а 1 - отвори.

Спробуйте в Інтернеті!

Як це працює

=þṗX¥S⁵*  Main link. Left argument: m. Right argument: n

    ¥     Combine the two links to the left into a dyadic chain and call it
          with arguments m and n.
  ṗ        Compute the n-th Cartesian power of [1, ..., m], i.e., generate all
           vectors of length n that consist of elements of [1, ..., m].
   X       Pseudo-randomly choose one of those vectors with a uniform distribution.
=þ        Equal table; for each k in [1, ..., m] and each vector to the right,
          compare the elements of the vector with k. Group the results by the
          vectors, yielding a 2D Boolean matrix.
     R    Range; map 1 to [1], 0 to [].
      S   Take the sum of all columns.
       ⁵* Raise 10 to the resulting powers.

10

Математика, 68 байт

Print/@(10^RandomSample@RandomChoice[IntegerPartitions[+##,{#}]-1])&

Безіменна функція, яка бере два цілих аргументи, кількість полів, а потім кількість елементів.

Він спочатку обчислює всі можливі розділи N+Mна точно Mпозитивні частини, а потім віднімає 1з кожного розділу. Це дає нам усі можливі розділи Nна Mнегативні частини (які IntegerPartitionsне генеруються інакше). Потім виберіть випадковий розділ і перемістіть його. Це гарантує, що всі можливі впорядковані розділи з нулями дозволені. І, нарешті, перетворити кожен бункер розділу на вихідну лінію за рахунок підвищення 10 до відповідної потужності (таким чином, що кожен рядок буде 1000...з kнулями). Приклад результату може виглядати так:

100
10000
1
10
10

Я вважаю, PadRightщо не став би Mнулями, якщо N< M.
LegionMammal978

1
@ LegionMammal978 Спасибі, вдалося виправити це в той же кількість байтів.
Мартін Ендер

... Я чесно вражений. Я збирався зробити подібне рішення, але PadRightйого нерозбірливість зробить це значно довше.
LegionMammal978

@ LegionMammal978 Інший спосіб уникнути PadRightб IntegerPartitions[#,{#2},0~Range~#].
Мартін Ендер

1
Ні буйтлін? Я здивований ...: D Але приємна відповідь. Мені просто потрібно розібратися, як це працює спочатку: P
HyperNeutrino

9

Python 2, 77 86 байт

from random import*
n,m=input()
exec'c=randint(0,n);n-=c;print 10**c;'*~-m
print 10**n

Створює число в [0, n], друкує, що багато елементів, і виводить його з n. Це роблять це м разів.

Це робить його малоймовірним, щоби що-небудь примусило його до останнього поля, але питання лише запитувало, щоб кожен вихід був можливим , не однаково вірогідним .


7

Пакетна, 164 байти

@for /l %%i in (1,1,%1)do @set h%%i=1
@for /l %%j in (1,1,%2)do @call set/ab=%%random%%%%%%%1+1&call set/ah%%b%%*=10
@for /l %%i in (1,1,%1)do @call echo %%h%%i%%

Я думаю, що 7 %знаків поспіль можуть стати новим особистим найкращим! Примітка: це створює непарний вихід, якщо він коли-небудь призначатиме більше 9 елементів одному і тому ж вікні; якщо це проблема, то на 180 байт:

@for /l %%i in (1,1,%1)do @set h%%i=1
@for /l %%j in (1,1,%2)do @call set/ab=%%random%%%%%%%1+1&call call set h%%b%%=%%%%h%%b%%%%%%0
@for /l %%i in (1,1,%1)do @call echo %%h%%i%%

Так, це %загалом 28 с на другому рядку.


5

C, 102 байти

n,m;main(x){srand(time(0));for(scanf("%d %d",&n,&m);m--;n-=x)printf("|%0*s\n",x=m?rand()%(n+1):n,"");}

Здійснює введення інформації про stdin, наприклад:

echo "5 4" | ./pigeonhole

Не генеруватиме кожен вихід з однаковою ймовірністю, але здатний генерувати всі можливі комбінації.

Зламатися:

n,m;
main(x){
    srand(time(0));             // Seed random number generator
    for(scanf("%d %d",&n,&m);   // Parse input values into n and m
        m--;                    // Loop through each bucket (count down)
        n-=x)                   // Subtract number assigned to bucket from total
        printf(                 // Output a formatted string using padding
            "|%0*s\n",          // (turns out %0s will actually zero-pad a string!)
            x=m?rand()%(n+1):n, // Calculate a number of items for this bucket
            "");
}

Покладається на обробку GCC з невизначеною поведінкою %0s- як правило, %0це нульове накладення цілого чи плаваючого, але воно може лише прокладати (ніколи не врізати), тому друкувати бланк неможливо. Але поведінка для рядків не визначено, і GCC вирішив зробити так само нульовий pad таким чином, що цей нульовий пробіл порожній рядок, щоб мати можливість записувати нуль або більше 0s.


2
Оскільки функції дозволені, ви можете відрізати кілька символів, використовуючи a(b,c){...}замість mainі scanf.
Кевін

3

Python 2, 102 99 97 90 байт

m-1разів, вибрали випадкову суму xміж 0і n, включно і відніміть її від n. Потім надрукуйте а 1та '0'*x.

Нарешті, надрукуйте 1і решту 0s. Зовсім не однакові шанси, але можливі всі конфігурації.

from random import*
n,m=input()
exec'x=randrange(n+1);n-=x;print 10**x;'*(m-1)
print 10**n

(Повторно використаний код із зламаної відповіді Python.)


Я думаю, що ця відповідь мала бути пропозицією щодо моєї відповіді, оскільки це буквально та сама відповідь з невеликим виправленням помилок.
orlp

1
@orlp Якщо ви подивитесь на історію цієї відповіді, це просто стало таким в останній версії. Якби я спочатку зробив це так, я б розмістив це як коментар.
L3viathan

Ага, то це добре, те, як він виглядав (і що ви написали "повторно використаний код"), зробив це виглядати інакше, ніж є. Вибачте.
orlp

@orlp Немає проблем. Ваш працює зараз і коротший, ніж мій, я також можу видалити цю відповідь, якщо ви вважаєте, що вона занадто близька до вашої, я не проти, просто хотів уточнити, що я не просто копіював і вставляв вашу відповідь.
L3viathan

3

Haskell, 114 94 байт

import System.Random
n#m=map(10^).take m.until((==n).sum.take m)tail.randomRs(0,m)<$>newStdGen

Трохи жорстокого підходу: формує нескінченний список випадкових чисел, бере n чисел початку списку, підсумовує їх і перевіряє, чи вони рівні m. Якщо ні, вийміть перший елемент зі списку і повторіть.

Спробуйте в Інтернеті!

Примітка: 73 байти без імпорту

EDIT: збережено кілька байтів за допомогою трюку 10 ^ ( Спробуйте нову версію в Інтернеті! )


2

REXX, 74 байти

arg n m
m=m-1
o.=@
do n
  a=random(m)
  o.a=o.a||#
  end
do a=0 to m
  say o.a
  end

Вихід (8 5):

@#
@###
@
@#
@###

Вихід (8 5):

@#
@#
@
@####
@##

2

C, 175 138 байт

Завдяки @Dave за економію 37 байт!

i;f(n,m){char**l=calloc(m,8);for(i=0;i<m;)l[i]=calloc(n+1,1),*l[i++]=124;for(i=n+1;--i;)*strchr(l[rand()%m],0)=35;for(;i<m;)puts(l[i++]);}

Спробуйте в Інтернеті!


1
Привіт, кілька речей, які можуть допомогти вам зменшити це: callocдадуть вам 0-ініціалізовану пам’ять (не потрібно встановлювати всі 0s самостійно), strchrзможете знайти кінець рядка, кома може ланцюгові операції, уникаючи необхідності {}та x[0] == *x. Також пильнуйте; у вас mallocнедостатньо пам'яті, якщо всі елементи знаходяться в одному полі.
Дейв

2

AHK, 66 байт

2-=1
Loop,%2%{
Random,r,0,%1%
Send,|{# %r%}`n
1-=r
}
Send,|{# %1%}

Я слідував за тим самим принципом, що і orlp , використовуючи випадкові числа від 0 до N, а потім віднімаючи його від N. На жаль, я не зміг зберегти байти, використовуючи 10 ^ r через те, як працює функція Send. На жаль і нахабство. Ось декілька виходів для n = 8, m = 5:

|##     |#####    |##       |##     |#      |##   
|##     |#        |#####    |       |###    |#    
|#      |##       |         |###    |###    |     
|###    |         |         |       |#      |     
|       |         |#        |###    |       |#####

2

CJam, 30 31 21 байт

:B1a*:C\{CBmrAt.*}*N*

Вхід - це два числа n mна стеку. Використовується 1для символу стовпця та 0для повторного символу.

Пояснення:

:B          e# Store m in B (without deleting it from the stack)
1a          e# Push 1 and wrap it in an array: [1]
*           e# Repeat the array m times
:C          e# Store this array in C (without deleting)
\{          e# Do n times:
  CBmrAt    e#   Create an array of 1s with a random element replaced with 10.
  .*        e#   Vectorized multiplication: multiply the respective elements in the arrays.
            e#   Effectively, we multiply a random value in the array by 10 (and add a 0 to the end).
}*          e# End loop.
N*          e# Join with newlines.


1

PHP, 100 байт

list($z,$m,$n)=$argv;$a=array_fill(0,$n,z);while($m>0){$a[rand(0,$n-1)].=a;$m--;}echo join("\n",$a);

Зламатися :

list($z,$m,$n)=$argv;     // assigns the input vars to $m and $n
$a=array_fill(0,$n,z);    // creates an array $a of $n elements containing 'z'
while($m>0){              // randomly populate array $a
    $a[rand(0,$n-1)].=a;  //
    $m--;                 //
}                         //
echo join("\n",$a);       // output $a contents separated by a new line

Виходи для m=7та n=5:

Перше виконання:

za
zaa
za
za
zaa

Друге виконання:

za
zaa
zaaa
z
za

Спробуйте в Інтернеті!


Ви можете використовувати [,$m,$n]=$argv;з PHP 7.1, щоб зберегти кілька символів. Ви можете замінити \nфактичним розривом рядка, щоб зберегти 1 байт. ви можете використовувати for(;$m-->0;)$a[rand(0,$n-1)].=a;для збереження перерв, $mкрапки та крапки з комою. [,$m,$n]=$argv;$a=array_fill(0,$n,z);for(;$m-->0;)$a[rand()%$n].=a;echo join("\n",$a);85 байт
Крістоф

Цей гольф знижує ще [,$m,$n]=$argv;for(;$m--;)${rand()%$n}.=a;for(;$n--;)echo"z${$n}\n";67 байт.
Крістоф

@Christoph Я бачив позначення [,$m,$n]=$argv;на інших кодах-гольфах, але не зміг змусити його працювати ні в моєму середовищі розробників, ні на eval.in
roberto06


1
Приємно. Я думаю, ви можете опублікувати свій фрагмент як відповідь, оскільки він досить сильно відрізняється від мого;)
roberto06,

1

JavaScript, 105 байт

x=>y=>{s=[];for(;x>1;y-=t)s[--x]="|"+"#".repeat(t=Math.random()*(y+1)|0);s[0]="|"+"#".repeat(y);return s}

Спробуйте в Інтернеті!

Завдяки способу призначення рядків це буде, як правило, більше розміщуватись у напрямку до низу, хоча є невелика ймовірність, що вершина отримає кілька.


1

Рубін, 52 байти

->(n,m){r=Array.new(m){?|};n.times{r[rand m]+=?#};r}

Створює анонімну функцію, яка бере два цілі числа в якості аргументів і повертає масив Strings:

>> puts ->(n,m){r=Array.new(m){?|};n.times{r[rand m]+=?#};r}.call 7,5
|#
|#
|##
|##
|#

1

Python 2, 81 байт

from random import*
def f(n,m):l=['#']*m;exec('l[randrange(m)]+="o";'*n);return l

Повертає список рядків.


1

Javascript (ES7), 75 байт

(N,M)=>{for(r='';M;M--,N-=x=~~(Math.random()*(N+1)),r+=10**x+`
`);return r}

Я вважав, що я розумний, щоб придумати ідею повноважень 10, щоб зрозуміти, що більшість відповідей уже використовують це.


1

AWK, 78 байт

{srand();for(;n++;)c[k]=c[k=int($2*rand())]"#"}END{for(;j<$2;)print"|"c[j++]}

Бере 2 аргументи, спочатку кількість предметів, потім кількість скриньок. Починається з висіву генератора випадкових чисел, тому кожен запуск відрізняється. Потім просто збирає рядки в масив, Приклад використання:

awk '{srand();for(;n++;)c[k]=c[k=int($2*rand())]"#"}END{for(;j<$2;)print"|"c[j++]}' <<< "12 5"

Example output:
|##
|###
|##
|##
|###

1

MATLAB, 103 94 байт

function a(m,n)
d=@(p)disp(char([1,~(1:p)]+48));for i=1:m-1;p=randi([0,n]);d(p);n=n-p;end;d(n)

З форматуванням

function a(m,n)
for i=1:m-1 
    d=@(p)disp(char([1,~(1:p)]+48));  % inline function for displaying
    p=randi([0,n]);              % picking a random number b/w 0 and n
    d(p);                        % '1' represents the box/pigeonhole, with '0's denoting entries
    n=n-p;
end
d(n);                            % writing the remaining entries/zeros

Вибірка зразка

>> a(4,7)
10
10000
10
10

Існують пробіли пробілів, оскільки кожен запис масиву відображається з вкладкою між ними, але це має бути прийнятним відповідно до специфікацій.

Це здається мені дуже спрощеною реалізацією, тому я впевнений, що це можна було б покращити.

Дякуємо @Luis Mendo за пропозиції.


Ви можете зберегти досить багато байт, визначаючи оператор відображення як анонімну функцію, щоб уникнути його написання двічі:d=@(p)disp(char([1,~(1:p)]+48));for i=1:m-1;p=randi([0,n]);d(p);n=n-p;end;d(n)
Луїс Мендо

@LuisMendo Дякую за пропозицію, я оновлю. Чи можу я так само визначити свою фактичну функцію, наприклад, a = @ (m, n) ... оскільки це також зменшить кількість байтів. Як люди, як правило, видаляють / скорочують "ім'я функції (args)" у відповідях коду MATLAB-гольфу?
Крост

Так, ви також можете використовувати анонімну функцію як відповідь. Можна навіть пропустити a=. У цьому випадку ви не можете цього зробити, оскільки анонімні функції не можуть містити циклів. Але ти можеш скористатися хитрістю вкласти все eval('...'). До речі, у Matlab це звичайно вважається некрасивим і поганим звичаєм, але тут ми любимо зловживати мовами :-)
Луїс Мендо

Хм .. Я оновлюсь на основі вашої пропозиції і подумаю ще трохи про це і побачу, чи зможу я уникнути циклу, хоча це здається малоймовірним. Я можу придумати логіку, яка могла б це зробити, але не знаю, як це здійснити. Я думаю про визначення числа 10 ^ n і знаходження m чисел, які мають усі потужності 10, а потім просто роздруковування їх. Це буде точно такий же вихід, як у мене зараз.: D Будь-які пропозиції? Сміливо опублікуйте це як іншу відповідь.
Крост

Я мав на увазі m факторів (не просто будь-яких чисел)
Крост


1

TI-Basic, 63 62 байти

Prompt N,M
For(A,1,M
N→B
If M-A
randInt(0,N→B
":→Str0
For(C,1,B
Ans+"X→Str0
End
Disp Ans
N-B→N
End

Кожне завдання повинно мати ненульову ймовірність обрання.

Цей критерій значно полегшив написання програми.

Приклад вводу / виводу:

prgmPIDGEON
N=?5
M=?2
:XXXX
:X

Пояснення:

Prompt N,M     # 5 bytes, input number of items, number of boxes
For(A,1,M      # 7 bytes, for each box
N→B            # 4 bytes, on last box, make sure the sum is met by adding N items
If M-A         # 5 bytes, if not last box
randInt(0,N→B  # 8 bytes, add random number of items from 0 to N to box A
":→Str0        # 6 bytes, first character
For(C,1,B      # 7 bytes, add B items to the box
Ans+"X→Str0    # 8 bytes
End            # 2 bytes
Disp Ans       # 3 bytes, print this box
N-B→N          # 6 bytes, subtract the items used in this box
End            # 1 byte, move on to next box

1

МАТЛАБ, 73 64 58 байт

Оновлення №3

Мені здається, потрібно сортувати, оскільки в іншому випадку я отримую від’ємні цілі числа. Я все ж замінив disp(sprintf(...))на fprintf(...)теперішній час, тому відповідь залишається 58 байт.

@(m,n)fprintf('%i\n',10.^diff([0;sort(randi(n,m-1,1));n]))

Оновлення №2:

Я зрозумів, що мені не потрібно сортувати масив, і насправді сортування фактично зменшить середнє число в масиві. Тому я sort(...)частину видалив . Зауважте, що вихід залишається тим самим, тому я не оновлюю "зразок виводу".

@(m,n)disp(sprintf('%i\n',10.^diff([0;randi(n,m-1,1);n])))

Нарешті, завершуємо відповідь Октави Луїсом! : D

Оновлення №1:

@(m,n)disp(sprintf('%i\n',10.^diff([0;sort(randi(n,m-1,1));n])))

Замість перетворення на рядок я просто відображаю цифри безпосередньо. Я міг скоротити до 58 байт, видалившиdisp(...) , але тоді я отримаю додатковийans = лише sprintf, і не знаю, чи це прийнятно.

Початковий код:

@(m,n)disp(strjust(num2str(10.^diff([0;sort(randi(n,m-1,1));n])),'left'))

Завдяки деяким пропозиціям Луїса я позбувся петлі у своїй попередній відповіді . Тепер я спершу створюю вертикальний масив mвипадкових чисел, додаючи доn ( diff([0;sort(randi(n,m-1,1));n])), потім використовую їх як експоненти 10, перетворюю їх у рядок, ліво-виправдовую їх та показую.

Я міг би технічно позбутися дисплей (...), щоб зберегти ще 6 байт, але потім надрукується "ans", який може порушити характеристики. Можливо, також є спосіб змінити їх на рядкові та ліві виправдання, щоб отримати бажаний кінцевий формат, тому я відкритий для пропозицій.

Вибірка зразка:

>> a=@(m,n)disp(strjust(num2str(10.^diff([0;sort(randi(n,m-1,1));n])),'left'));
>> a(4,6)
1000
10  
100 
1   

Примітка : я змінив свою функцію на анонімну функцію тут, грунтуючись на пропозиціях. У вибірку вибірки я призначив це дляaтого, щоб продемонструвати. Я сподіваюся, що це не порушує характеристики, але якщо це, будь ласка, дайте мені знати, і я це зміню.


Я щойно зрозумів, що головна відповідь використовує ту саму логіку 10 ^ .. Для чого це варто, і якщо це важливо, я не використовував це як орієнтир для своєї відповіді .. (але бадьоро, хтось побив мене на це!: П)
Крост

Також я хотів відзначити цю відповідь за ідею створення mвипадкових цілих чисел, які додаються до n, оскільки я довгий час застряг у цій частині .. (Ще не можу додати більше 2 посилань у своїх відповідях, включаючи це у коментарі)
Крост

1

Зіставлено , 29 байт

('|')\rep\[:randin'#'push@.]*

Спробуйте в Інтернеті!

Поводить себе, будуючи масив Mсинглів, що містить '|', а потім додає '#'до випадково вибраного Nчасу масиву .


Приємно! І тому всі результати однаково ймовірні, правда?
Луїс Мендо

@LuisMendo так і має бути, оскільки randinвикористовує алгоритм Fisher-Yates всередині країни. (Це той самий алгоритм, у якому відповідь CJam використовує FWIW)
Conor O'Brien

1

Python 2 , 80 95 89 88 байт

from random import*
n,m=input()
while m:x=randint(0,n);print'1'+'0'*[n,x][m>1];m-=1;n-=x

Спробуйте в Інтернеті!

  • Додано 15 байт: Попереднє редагування було дещо помилковим, деякі п’єгони залишилися осторонь.
  • Збережено 6 байт: замінено на [n, x] [m> 1]
  • Збережено 1 байт: імпорт *

1

Вугілля деревне , 19 байт

≔EN⟦⟧θFN⊞‽θ#Eθ⁺|⪫ιω

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

  N                 Input `M`
 E                  Map over implicit range
   ⟦⟧               Empty array
≔    θ              Assign resulting nested array to `q`

       N            Input `N`
      F             Loop over implicit range
          θ         Nested array `q`
         ‽          Random element
           #        Literal string
        ⊞           Append to array

             θ      Nested array `q`
            E       Map over array
                 ι  Current element
                  ω Empty string
                ⪫   Join
               |    Literal string
              ⁺     Concatenate
                    Implicitly print on separate lines
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.