Порівняйте номери версій


26

Коли ми публікуємо деяке програмне забезпечення, ми присвоюємо йому номер версії. І користувачі можуть захотіти оновити до останньої версії деякого програмного забезпечення. Отже, саме час з’ясувати, яка версія повинна бути новішою.

Вхідні дані

Введіть два ряди версій як рядки.

У контексті цього виклику ми підтримуємо лише номери версій, які є деякими цифрами, об'єднаними крапками.

  • Номер версії - це рядок, який може містити лише цифри ( 0~ 9) і крапки ( .).
  • Крапки не будуть першим / останнім символом номера версії.
  • Між крапками повинно бути кілька цифр. Ні дві точки не можуть з’являтися постійно.
  • Усі номери у номері версії становитимуть менше 2 16 .

Вихідні дані

Порівняйте введені номери версій та виведіть, чи перша перша / менша / менша, ніж друга. Ви можете вибрати одну з наступних презентацій:

  • Використовуйте додатне число / нуль / від’ємне число, тоді як нуль означає рівне;
  • Використовуйте три постійні чіткі значення;

Порівнюючи

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

  • Номери версій - це десяткові числа, об'єднані крапками. Ми спочатку розділили два числа версій на масиви чисел;
  • Прошивання закінчення масивів нулями, щоб вони мали однакову довжину;
  • Порівняйте від першого до останнього:
    • Якщо два елементи масиву різні, то більша кількість означає більший номер версії
    • Якщо вони однакові, продовжуйте порівнювати наступні пункти;
    • Якщо всі елементи в масиві рівні, дві версії рівні.

Тестові шафи

version1  version2  result
2         1         >
1.0.0     1         =
1.0       1.0.0     =
1.2.42    1.2.41    >
1.1.56789 1.2.0     <
1.10      1.2       >
1.20      1.150     <
18.04     18.4      =
7.010     7.8       >
1.0.0.1.0 1.00.00.2 <
00.00.01  0.0.0.1   >
0.0.1     0.1       <
42.0      4.2.0     >
999.999   999.999.1 <
2018.08.1 2018.08   >


.NET має об’єкт Версія, але жоден символ не підтримується в ньому :(
Brian J

@BrianJ і додавання ".0" коштує багатьом символам? :)
RobAu

Ну, насправді очікують 2, 3 або 4 порції. Тож це не вдається на тестовому випадку 1.0.0.1.0 (хоча я спробував вашу ідею спочатку :))
Brian J

Я думаю, що у Windows є вбудований модуль, який зробить це так: StrCmpLogicalW
bace1000

Відповіді:



6

05AB1E (спадщина) , 15 14 13 байт

'.¡0ζε`.S}0K¬

Виходи -1 [] 1для < = >відповідно.

-1 байт завдяки @Emigna .

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

'.¡              # Split on dots
                 #  i.e. ['1.0.1.1.0','1.00.2.0']
                 #   → [['1','0','1','1','0'],['1','00','2','0']]
   0ζ            # Zip, swapping rows and columns, using '0' as filler
                 #  i.e. [['1','0','1','1','0'],['1','00','2','0']]
                 #   → [['1','1'],['0','00'],['1','2'],['1','0'],['0','0']]
     ε   }       # Map each:
      `          #  Push both values to the stack
       .S        #  And calculate the signum (1 if a>b; -1 if a<b; 0 if a==b)
                 #   i.e. [['1','1'],['0','00'],['1','2'],['1','0'],['0','0']]
                 #    → [0,0,-1,1,0]
          0K     # Remove all zeros
                 #  i.e. [0,0,-1,1,0] → [-1,1]
            ¬    # Then take the head as result
                 #  i.e. [-1,1] → -1

1
Ви можете використовувати 0Kзамість ʒĀ}.
Емінья

@Emigna Ну звичайно .. Дякую.
Кевін Круїссен

5

R , 32 байти

rank(numeric_version(scan(,"")))

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

Використання вбудованого R

Виходи 1 2, 1.5 1.5, 2 1для менше, так само, більше.


Кращий поки що без вбудованого:

R , 151 142 125 107 байт

function(v,L=strsplit(v,'\\.'))Find(c,sign(Reduce('-',Map(as.double,Map(c,L,Map(rep,0,rev(lengths(L))))))))

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

Розкручений код із поясненням:

function(v){             # character vector of 2 elements as function arg;
  L=strsplit(v,'\\.')    # obtain a list of two character vectors
                         # with the separated version numbers;
  R=rev(lengths(L))      # store in vector R the lengths of the 2 vectors and reverse it;
  M1=Map(rep,0,R)        # create a list of 2 vector containing zeros
                         # repeated R[1] and R[2] times;
  M2=Map(c,L,M1)         # append to the vectors in list L the zeros in M1;
  M3=Map(as.double,M2)   # convert the character vectors in M2 to double;
  w=sign(Reduce('-',M3)  # compute the sign of element by element difference M[[1]] - M[[2]]);
  Find(c,w)            # returns the first non zero element in w, if none return NULL;
}
# N.B. as.double is necessary because "0XX" is interpreted as octal by strtoi unless 
#      we use strtoi(x,10) which is exactly the same length of as.double(x)

Виходи -1, NULL, 1для менше, так само, більше.


Оригінальна концепція, використана в гольф sapply, [<-і %*%:

R , 129 байт

function(x,y=strsplit(x,"\\."),w=sign(sapply(y,function(x)strtoi("[<-"(rep(0,max(lengths(y))),seq(x),x),10))%*%c(1,-1)))w[!!w][1]

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

Тепер у вас є список двох векторів рівних довжин цілих чисел. Обчисліть попарні різниці, використовуючи Reduceта виведіть перший ненульовий елемент, використовуючи складну маленьку w[!!w][1]форму в кінці.

Виходи -1, NA, 1для менше, так само, більше.


Вражає! Швидкий гольф: додатковий новий рядок в кінці коду - він повинен бути 150 байт;)
JayCe

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

1
Ви можете опустити це до 100 байт, використовуючи scan function(a,b,d=scan(t=a,se='.'),e=scan(t=b,se='.'),f=1:max(lengths(list(d,e))),g=d[f]-e[f])g[!!g][1](або 106, якщо хочете повернути -1, NA, 1 не (негативне), NA, (позитивне).
mnel

1
@mnel 100-байтному рішенню потрібно трохи попрацювати. Він не вдається на двох останніх тестових випадках. 0Прокладка повинна бути, а не (неявно) NA. Я відповів на спільноту Wiki, тому кожен, хто може її виправити, може просто додати її.
ngm

1
@digEmВсі чотири байти в гольф, спочатку обчисливши знак, а потім зробіть Find(c,x). Я думаю, що це новий трюк.
JayCe

4

APL (Dyalog Unicode) , 18 17 байт

1 байт збережено завдяки @ Adám за використання ⍤1замість ∘↑(...)¨та зміну вхідного формату з вкладеного масиву в матрицю

(⍋-⍒)(⍎¨∊∘⎕D⊆⊢)⍤1

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

Приймає введення як матрицю символів як правильний аргумент, де кожен рядок версії знаходиться у своєму рядку. Виходи ¯1 1, 0 0, 1 ¯1для <, =, >відповідно.

(⍎¨∊∘⎕D⊆⊢)⍤1 на кожному ряду

  • ∊∘⎕D⊆⊢ згрупуйте всі входження цифр, тобто розділіть на .

  • ⍎¨ і перетворити кожне з цих подій у число

перетворити в матрицю, де перший вхід знаходиться у верхньому рядку, а другий - у нижньому, закладаючи з 0s, де потрібно

(⍋-⍒) і

  • - відняти
    • індекси в рядки, які б сортували їх у порядку зменшення
    • те саме, що верх, але для порядку зростання

4

Perl 6 , 63 47 22 байт

{"v$^a cmp v$^b".EVAL}

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

Виявляється, Perl 6 має тип версії, який майже відповідає опису. Це анонімний блок коду, який містить список з двох рядків версії та повертає або More, Sameабо Less.

Пояснення:

{                    }  # Anonymous code block
 "             "        # Create a string of code
  v$^a cmp v$^b         # Comparing the two versions
                .EVAL   # And EVAL it

Або без вбудованих типів на 47 байт:

{first +*,[Z<=>] map *.split('.')[^@_.ords],@_}

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

Блок анонімного коду, який займає два рядки і повертається, Moreякщо другий більший, Lessякщо другий менший і Nilякщо вони рівні.

Пояснення:

{                                             } # Anonymous code block
                 map *.split('.')          ,@_  # Split both strings by '.'
                                 [^@_.ords]     # Pad the lists by a lot
          [Z<=>]   # Zip the strings with the <=> operator
 first +*,  # Get the first value that when coerced to an int, is not 0

3

Брахілог , 49 40 байт

+0|{~c[H,".",T]hị;T|ị;0|0}ᵐz{h-0&t↰₀|h-}

... Він все ще досить невразливо тривалий.

Очікує список двох рядків. Використовує positive number / zero / negative number як > / = / <.

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

Пояснення

Розбиття входів

Беручи під увагу , що вхід не уніфікувати з [0, 0], наприклад ["1.02.0", "1.2.0.1.0"], нижче виходів сегментів, наприклад, [[1, "02.0"], [1, "2.0.1.0"]].

                            # unify the input with...
+0                          # : a list whose sum = 0 (output is 0)
  |{                     }ᵐ # : OR a list that when mapped...
    ~c                      # : : if the input string unifies with a list of the form...
      [H,".",T]             # : : : e.g. "1.02.0", H = "1", T = "02.0"
               hị           # : : : coerce the head to an integer
                 ;T         # : : : append the string T
                            # : : : "1.02.0" -> [1, "02.0"]
                   |ị       # : : OR it unifies with an integer
                     ;0     # : : : append 0
                            # : : : "1" -> [1, 0]
                       |0   # : : OR it unifies with 0
                            # : : : 0 -> [0]

Порівняння входів

Дано, наприклад, [[1, "02.0"], [1, "2.0.1.0"]]перетягує підсписи на [[1, 1], ["02.0", "2.0.1.0"]]та порівнює значення в голові ( [1,1]). Повторіть другий підпис. Зауважте, що zцикл предикатів zip через коротші списки, так що блискавка з [0,0]еквівалентом блискавки [0], отже, попередній крок уніфікується 0з 0додатковими значеннями, що додаються.

z             # zip the sublists
 {          } # unify the result (r) with...
  h           # : take the head of the result
   -          # : : subtract the second value from the first
    0         # : : if the difference unifies with 0...
     &t↰₀     # : : recur on the tail of r
         |h-  # : OR unify with the difference of the elements of the head
              # : (equivalent to returning early)

3

JavaScript (ES6), 73 68 байт

Збережено 5 байт завдяки @redundancy

(a)(b)0

a=>b=>(a+[...b].fill`.`).split`.`.some((x,i)=>d=~b.split`.`[i]-~x)*d

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


Приємно. Якщо я правильно зрозумів, ви можете зберегти байти, замінивши replaceна fill. Операнди для -обмінюються, оскільки обидва тепер повинні бути примушені до числа. Спробуйте в Інтернеті!
надмірність

@redundancy Гарна ідея! (Не впевнений, чи моє реалізація саме те, що ви мали на увазі.)
Арнольд,

Я припустив , ваш намір було докласти чималих значення стискається до 0 таке , що відображення над підрядками в aкінці кінців циклів з допомогою цих значень 0 , якщо bмістить більше сегментів , ніж числа a. Так трапляється, що найкоротшим методом забезпечення цього є розділення на bдовгу рядок '. шляхом використання існуючого розколу, застосованого до a.
надмірність

3

Java (JDK 10) , 201 96 89 байт

java.util.Comparator.comparing(java.lang.module.ModuleDescriptor.Version::parse)::compare

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

Повертає від'ємне число, якщо перша версія менша за другу, додатна, якщо перша версія більша за другу і 0якщо вони рівні.

Так, це якась важка робота, щоб "просто" зателефонувати на вбудований!

Кредити


1
Я спробував, але мені вдалося видалити лише три байти .. 228 байт
Кевін Круїйсен

1
Знайдено щось більше: 217 байт
Кевін Круїссен

1
Це, мабуть, це .. Вже спробував, try-finallyтому перевірку if можна спростити; намагався повернутися всередину циклу, якщо t!=0; спробував використовувати Integerі i.compare(i.valueOf(...),i.valueOf(...)); спробував використовувати подібні дженерики <T>T[]g(T s){return(T[])(s+"").replaceAll("(\\.0+)*$","").split("\\.");}; і т.д. Усі на 2-6 байт довше. Якщо ви (чи хтось інший) все-таки знайдете щось більше, дайте мені знати, будь ласка. Цікаво знати, що. :)
Кевін Круїссен

1
@KevinCruijssen Ні, я не можу, тому що "Усі номери у номері версії будуть меншими за 2^16". Короткі діапазони від - (2 ^ 15) до 2 ^ 15-1.
Олів'є Грегоар

1
@KevinCruijssen я міг видалити 105 байт! Як? Ну, я знайшов вбудований;)
Олів'є Грегоар


2

Сітківка 0.8.2 , 54 байти

\d+
$*
+`^(.)(.*=)\1
$2
(.*=|^=.*)1.*
<
.*1.*=.*
>
\.

Спробуйте в Інтернеті!Посилання включає тестові випадки. Використовує значення роздільника як вихід рівності, тому для зручності заголовок перетворює вхідний роздільник, =але це може бути все, що не має [.\d]. Пояснення:

\d+
$*

Перетворити в одинарне.

+`^(.)(.*=)\1
$2

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

  1. Якщо жоден рядок не містить 1 результат є=
  2. Якщо ліва рядок починається з а 1 а, результат є>
  3. Якщо правий рядок починається з а 1 то результат є<
  4. Якщо ліва рядок порожній, результат є <
  5. У цей момент правий рядок порожній, тому результат є >

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

(.*=|^=.*)1.*
<

Перевірте випадок 3 або випадок 4 без справи 1.

.*1.*=.*
>

Якщо ліва рядок все ще містить в 1цій точці, то вона більша.

\.

В іншому випадку видаліть все, що залишилося . s.

Консоль браузера Firefox REPL, 19 байт

Services.vc.compare

Я вважаю, що ця внутрішня функція виконує необхідне порівняння. Він повертає -1, 0 або 1.


1
Я б запропонував вам опублікувати хром Firefox як іншу відповідь ...
tsh

btw, я не впевнений, як хром-код Firefox рахує його байти. Чи Cu.import("resource://gre/modules/Services.jsm");слід рахувати?
TSH

1
@tsh Тому я додав "Консоль браузера REPL" ...
Ніл

2

PHP , 38 байт

<?=version_compare($argv[1],$argv[2]);

Виходи -1 → < | 0 → = | 1 → >

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


Я думаю, що ваше подання може бути лише самою функцією
Джо Кінг,

1
Це повертає невірний результат для будь-якої пари входів, які відрізняються лише кінцевими нулями, наприклад, 1.0.0і1
oktupol

2

C (gcc) ,  140  134 байт

Цей код виводить мінус, 0або додатник для <, =або> відповідно.

i;n;p;q;g(char*s){for(i=n=0;*s&&++n&&*s-46;i=i*10+*s++-48);i=i;}f(char*a,char*b){for(p=q=0;*a+*b&&p==q;b+=n)p=g(a),a+=n,q=g(b);a=p-q;}

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

Зміни:

  • Збережено 6 байт завдяки стельовій кішці!

У виклику зазначено: "Використовуйте три постійні чіткі значення;" Ваш код не повертає константи.
Олів'є Грегоар

1
@Olivier Вказується, що я можу "використовувати три постійні чіткі значення;" АБО "Використовуйте додатне число / нуль / від'ємне число, тоді як нуль означає рівне;"
Аньйо

Моє ліжко! Ви маєте рацію.
Олів'є Грегоар


1

JavaScript (Node.js) , 105 88 80 байт

-17 байт від @redundancy. Оце Так!

-8 байт видалення Math.sign. Дякую @tsh

Повертає негативне, нульове або додатне значення

f=(a,b,r=/(\d*).?(.*)/)=>a+b&&+((a=r.exec(a))[1]-(b=r.exec(b))[1]||f(a[2],b[2]))

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


1
88 байт, використовуючи execдля розділення рядків. Спробуйте в Інтернеті!
надмірність

@redundancy Чорт, дякую! ось досить прикольний трюк
Луїс феліпе Де ісус Муноз

Можливо, ви хочете видалити Math.sign, щоб зберегти деякі байти, перейшовши на значення позитивні / нульові / негативні. І, можливо, потрібен позитивний знак.
tsh

1

Japt , 16 11 байт

-5 байт від @Shaggy

Виходи:

  • від’ємне число для <
  • ( nullабо 0) для=
  • додатне число для >

N®q.Ãy_r-Ãf

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


Буде чи ця робота?
Кудлатий

@Shaggy Так, це може бути скорочено до 10 байтів, виводячи мінус, нуль або 0, додатно < = >відповідно, але я не знаю, чи можна вводити вхід як масив
Luis felipe De jesus Munoz

0

Чисто , 116 111 байт

import StdEnv,Text
?s=map toInt(split"."s)
$a b= @(?a)(?b)
@[h:t][u:v]|h==u= @t v=h-u
@l[]=sum l
@[]l= ~(sum l)

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

Виводить негативне число, коли перший аргумент менший за другий, нульовий, коли вони еквівалентні, і додатне число, коли воно більше, ніж друге.


0

Швидкий 4 , 155 байт

Заголовок (не рахується: код нерекурсивний):

let f:(String,String)->Bool? = 

Код

{let x:(String)->[Int]={$0.split{$0=="."}.map{Int($0)!}.reversed().drop{$0==0}.reversed()},a=x($0),b=x($1)
return a==b ?nil:a.lexicographicallyPrecedes(b)}

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

Пояснення

  • Обрізаємо трейлінг .0.
  • Ми порівнюємо компоненти чисельно.

Повернулися константи

  • нуль для =
  • вірно для <
  • false for>

0

JavaScript 64 байти

a=>b=>(e=i=>(g=v=>v.split`.`[i]||0)(a)-g(b)||!a[i]-1&&e(i+1))(0)

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

З коментарями:

a=>b=>(                            // Main function takes arguments like ("1.2.42")("1.2.41")
    e=i=>                          // e(i) compares the ith number, returns >0, <0 or =0.
        (   g=v=>v.split`.`[i]||0  // g() returns the ith string or 0
        )(a)                       // call g(a)
        -g(b)                      // subtracting g(b) from g(a) casts strings to integer
        ||                         // If they are not equal return result now
        !a[i]-1 &&                 // recursion limited to a.length, always sufficient
        e(i+1)                     // next i
    )(0)                           // Start with i = 0


0

Бурлеск - 17 байт

wd{'.;;)ri}m[^pcm


blsq ) "2018.08.1 2018.08"wd{'.;;)ri}m[^pcm
1
blsq ) "0.0.1 0.1"wd{'.;;)ri}m[^pcm
-1
blsq ) "1.1.56789 1.2.0"wd{'.;;)ri}m[^pcm
-1

Якщо ви хочете вивести в '> <=', тоді додайте ?i"<=>"j!!Q.


0

Powershell, 88 байт

Повертається 0для рівних, a positive integerдля більше або a negative integerдля менше.

param($a,$b)+(($x=$a-split'\.')+($y=$b-split'\.')|%{$x[+$i]-$y[$i++]}|?{$_}|Select -f 1)

Менш тестовий сценарій для гольфу:

$f = {

param($a,$b)
$x=$a-split'\.'
$y=$b-split'\.'
$z=$x+$y|%{
    $x[+$i]-$y[$i++]
}|?{$_}|Select -first 1
+$z             # convert $null to 0

}

@(
    ,("2"         ,"1"         , 1)
    ,("1.0.0"     ,"1"         , 0)
    ,("1.0"       ,"1.0.0"     , 0)
    ,("1.2.42"    ,"1.2.41"    , 1)
    ,("1.1.56789" ,"1.2.0"     ,-1)
    ,("1.10"      ,"1.2"       , 1)
    ,("1.20"      ,"1.150"     ,-1)
    ,("18.04"     ,"18.4"      , 0)
    ,("7.010"     ,"7.8"       , 1)
    ,("1.0.0.1.0" ,"1.00.00.2" ,-1)
    ,("00.00.01"  ,"0.0.0.1"   , 1)
    ,("0.0.1"     ,"0.1"       ,-1)
    ,("42.0"      ,"4.2.0"     , 1)
    ,("999.999"   ,"999.999.1" ,-1)
    ,("2018.08.1" ,"2018.08"   , 1)
) | % {
    $v1,$v2,$expected = $_
    $result = &$f $v1 $v2
    "$([Math]::Sign($result)-eq$expected): $result"
}

Вихід:

True: 1
True: 0
True: 0
True: 1
True: -1
True: 8
True: -130
True: 0
True: 2
True: -1
True: 1
True: -1
True: 38
True: -1
True: 1

0

Дарт , 277 231 байт

F(s,{t}){t=s.split('.').map(int.parse).toList();while(t.last<1)t.removeLast();return t;}f(a,b,{d,e,f,g,h,i=0}){d=F(b);e=F(a);g=d.length;h=e.length;f=h>g?g:h;for(;i<f;i++)if(e[i]!=d[i])return e[i]>d[i]?1:-1;return h>g?1:(h<g?-1:0);}

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

  • -44 байти, використовуючи змінні для зберігання довжини та використання терміналу в циклі
  • -2 байти, знявши дужки для дужок

0

Swift 4 + Foundation , 160 байт (142 + 18) , 155 байт (142 + 13)

Імпорт (13 байт, у тому числі ;для відокремлення від коду):

Це імпортуватиме Foundation, але на 5 байт коротше import Foundation.

import UIKit;

Заголовок (не рахується: код нерекурсивний):

let f:(String,String)->ComparisonResult =

Код (142 байти):

{var x={($0 as String).split{$0=="."}.count},a=$0,b=$1
while x(a)<x(b){a+=".0"}
while x(b)<x(a){b+=".0"}
return a.compare(b,options:.numeric)}

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

Пояснення

  1. Додаємо деякий кінцевий .0 для тієї ж кількості компонентів.
  2. Ми порівнюємо компоненти чисельно.

Повернулися константи

  • ComparingResult.orderedSame for =
  • ПорівнянняРезультат.порядкованогоЗазміщення для <
  • ComparingResult.orderedDescending for>

Я не впевнений, чи будемо ми рахувати importтвердження, тому я опублікував окрему відповідь , яка не потребує, Foundationі байти рахують між 142 байтами (не рахуючи імпорту) та 160 байтами (рахуючи імпорт).
Cœur

0

Zsh , 54 байт

eval {autoload,}' is-at-least $'{1\ $2,2\ $1}';<<<$?;'

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

Це evalстосується наступних восьми тверджень:

autoload is-at-least $1 $2     # loads the "is-at-least" function
<<<$?                          # success, prints 0
autoload is-at-least $2 $1     # redundant
<<<$?                          # success, prints 0
is-at-least $1 $2              # exits 1 if $1 < $2
<<<$?
is-at-least $2 $1              # exits 1 if $2 < $1
<<<$?

Отже, три унікальні значення:

 cmp |  value
-----+------------------------------------------
  =  |  0<newline>0<newline>0<newline>0<newline>
  <  |  0<newline>0<newline>1<newline>0<newline>
  >  |  0<newline>0<newline>0<newline>1<newline>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.