Сделайте миску супа алфавита


55

Это то, что мы назовем тарелкой супа с алфавитом - примерно круглая форма ascii-art с 26 заглавными буквами английского алфавита (AZ), расположенными по часовой стрелке для формирования периметра:

   XYZABC
 VW      DE
U          F
T          G
S          H
 RQ      JI
   PONMLK

Напишите программу, которая принимает один буквенный символ AZ и выводит ту же самую чашу алфавитного супа, так сказать, «повернутую», чтобы входная буква появлялась там, где Aв приведенном выше примере это происходит, а остальная часть алфавита полностью циклически вращается. по часовой стрелке.

Таким образом, результатом для ввода Aбудет та же самая оригинальная миска супа из алфавита.

И вывод для ввода Bбудет такой:

   YZABCD
 WX      EF
V          G
U          H
T          I
 SR      KJ
   QPONML

Аналогично, результат Hбудет:

   EFGHIJ
 CD      KL
B          M
A          N
Z          O
 YX      QP
   WVUTSR

Или для Z:

   WXYZAB
 UV      CD
T          E
S          F
R          G
 QP      IH
   ONMLKJ

Это должно работать для всех 26 букв, от A до Z.

Подробности:

  • Можно предположить, что единственным вводом будет одна буква от A до Z.
  • Если удобно, вы можете использовать строчные буквы az для ввода и / или вывода, вы можете даже смешивать и сочетать строчные и прописные буквы.
  • Порядок алфавита должен вращаться по часовой стрелке, а не против часовой стрелки.
  • Вы должны использовать пробелы, а не что-то еще, чтобы сделать отступ и заполнить суповую тарелку.
  • На выходе могут быть начальные или конечные символы новой строки или пробелы, если тарелка супа расположена правильно.
  • Обратите внимание, что форма чаши имеет ширину 12 символов и высоту 7, чтобы текст выглядел примерно круглым. Ваши миски должны быть одинаковой формы.

Это кодовый гольф, поэтому выигрывает самый короткий код!


12
Отличный вызов! Сначала это кажется легким, но это не так
Луис Мендо

Ответы:


22

05AB1E , 21 байт

Определяет программуf:AlphabeticCharString

Код:

2AA¹k._•1못*Ć,ãiDΣ•Λ

Попробуйте онлайн!


Сломать:

2AA¹k._•1못*Ć,ãiDΣ•Λ

2                       # <length>
 AA¹k._                 # <filler>
       •1못*Ć,ãiDΣ•    # <pattern>
                    Λ   # Invoke the canvas function.


Объяснение:

Холст ( Λ) в данном контексте работает как функция со следующей подписью:

Λ:(length:Nat, filler:String, pattern:Nat)String

Параметр в этой ситуации является числом, определяющим направления. В коде это число представляется как , представляющее собой сжатую версию большого числа . Направления обозначаются следующим образом:pattern 2232344565666667670012122•1못*Ć,ãiDΣ•2232344565666667670012122


70162543


Это означает, что большое число представляет следующий шаблон направлений:

[,,,,,,,,,,,,,,,,,,,,,,,,]

С этим контекстом подписи холст перебирает список и записывает символы из в текущем направлении.patternlengthfiller

задается в коде как (в начале кода). Для нам нужна повернутая версия алфавита, которая начинается с заданного ввода. Это делается с помощью следующего кода ( попробуйте здесь ):length2filler

AA¹k._

 A¹k # Найти <индекс> данного входного символа в алфавите
A ._ # Поверните алфавит влево <index> раз.

В псевдокоде это будет выполняться функцией canvas:

1.Write ab in the direction2.Write bc in the direction3.Write cd in the direction4.Write de in the direction5.Write ef in the direction6.Write fg in the direction

Наконец, вы можете видеть, что аргумент заполнителя «повернут» раз вправо, что означает, что холст будет перебирать следующий (циклический и, следовательно, бесконечный) список:length1

[ab,bc,cd,de,ef,fg,gh,hi,ij,jk,...

Что приводит к желаемому алфавитному супу ascii-art shape.


Хорошо, я сдаюсь. Пытался найти более короткие альтернативы, но я этого не вижу. AA¹k._альтернативно может быть A¹¡RJ«, но это тот же счетчик байтов. •1못*Ć,ãiDΣ•альтернативно может быть •õÕ₆qηµñ–†f•·, но это тот же счетчик байтов. Ах хорошо. Хороший ответ!
Кевин Круйссен

11

Perl 6 , 100 байт

{"2XYZABC
 VW5DE
U9F
T9G
S9H
 RQ5JI
2PONMLK".trans(/\S/=>{(try ' 'x$/+1)||chr ($/.ord+.ord)%26+65})}

Попробуйте онлайн!

Заменяет все буквы в строке их сдвинутыми аналогами, при этом цифры заменяются числом пробелов, которые они представляют, плюс один.

объяснение

{                                                            }# Anonymous code block
 "...".trans(/\S/=>{                                       }) # Translate non-whitespace
                    (try ' 'x$/+1)      # If digits, the amount of spaces plus one
                                  ||chr ($/.ord+.ord)%26+64  # Else the shifted letter


9

Рубин , 107 байт

->n{a=(0..6).map{' '*11}
(?A..?Z).map{|i|j,k=(1i**((i.ord-n.ord-6)/6.5)).rect;a[3.5*k+=1][5.2*j+6]=i}
a*$/}

Попробуйте онлайн!

Улучшенный синтаксис "i".to_c-> 1i(предложено Джорданом)

Изменена система координат, так что 0 градусов справа, а не сверху. Это позволяет 0.5->6

Скорректированы множители jи kдля краткости

Вместо вывода на печать puts aобъедините элементы массива и верните строкуa*$/

Рубин , 119 байт

->n{a=(0..6).map{' '*11}
(?A..?Z).map{|i|j,k=("i".to_c**((i.ord-n.ord+0.5)/6.5)).rect;a[3.5-j*3.3][6+k*5.17]=i}
puts a}

Использует комплексное число, возведенное в степень для отображения на эллипс. Полный ход равен 26, поэтому каждый квадрант равен 6,5.

Этот подход опирается на требуемые выходные данные, достаточно напоминающие эллипс, чтобы можно было получить правильное отображение.

Попробуйте онлайн!


@ Иордания спасибо, я не видел этот синтаксис раньше!
Уровень Река St

8

Древесный уголь , 33 байта

GH→→↘→↘↓↓77←←←←↖←↖↑↑↗→↗→→²✂⁺αα⌕αS

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

GH

Проследить путь.

→→↘→↘↓↓77←←←←↖←↖↑↑↗→↗→→

Обрисуйте миску. Каждый 7расширяется до ↙←.

²

Перемещайте по одному символу за раз (этот API перекрывает концы каждой строки следующим).

✂⁺αα⌕αS

Рисуйте, используя удвоенный алфавит, но начиная с позиции вводимого символа.


8

MATL , 49 байт

7I8*32tvB[1b]&Zvc2Y2j7+_YSy&f7-w4-_Z;YPE\,&S])yg(

Какой беспорядок Но было весело писать. Там даже арктангенс вовлечен.

Попробуйте онлайн!

объяснение

Код

7I8*32tvB

создает массив чисел и преобразует их в двоичные. Это дает матрицу ноль-один

0 0 0 1 1 1
0 1 1 0 0 0
1 0 0 0 0 0
1 0 0 0 0 0

который является верхним левым квадрантом матрицы, определяющей положение букв.

[1b]&Zv

отражает этот квадрант по вертикали, не повторяя последнюю строку, и по горизонтали повторяя последний столбец, чтобы получить полную матрицу:

0 0 0 1 1 1 1 1 1 0 0 0
0 1 1 0 0 0 0 0 0 1 1 0
1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 1
0 1 1 0 0 0 0 0 0 1 1 0
0 0 0 1 1 1 1 1 1 0 0 0

Теперь у нас есть маска с позициями. Код

c

преобразует это в char, потому что конечным результатом будет матрица char. Символ 0 отображается как пробел, и ненулевые записи будут записаны с соответствующими буквами.

2Y2

толкает строку 'abc···xyz', которая содержит 26 букв. Эта строка должна быть смещена по кругу согласно входу. Для этого

j7+_YS

читает входную букву, добавляет 7 к своему ASCII-коду и отменяет результат. Для ввода 'a'это дает -104, который кратен 26, поэтому круговое смещение на эту величину ничего не изменит. Если на входе bэто дает -105, что сдвигает строку на 1 шаг влево для получения 'bcd···yza'; и т.п.

Следующим шагом является определение порядка, в котором смещенная строка будет записана в ненулевые элементы матрицы. С этой целью,

y&f

создает копию матрицы и выдвигает два вектора, содержащих позиции строк и столбцов ненулевых элементов на основе 1. затем

7-w4-_

вычитает 7 из второго, выводит первое на верх, вычитает 4 из него и отрицает его. 7 и 4 задают начало координат, так что углы векторов позиций ненулевых элементов относительно этого начала определяют желаемый порядок.

Z;YPE\

вычисляет арктангенс с двумя аргументами по модулю 2 * pi, чтобы получить эти углы. Теперь наименьший угол, равный 0, соответствует записи, куда должна идти первая буква, а остальные - против часовой стрелки.

,&S])

переставляет буквы в строке в соответствии с этими углами, так что, когда буквы записываются в ненулевые записи матрицы в мажорном порядке (вниз, затем поперек), результат будет правильным. Это сделано

yg(

Например, если входная 'a'строка не была смещена по кругу:

abcdefghijklmnopqrstuvwxyz

Перестановка по углам превращает это в

utsvrwqxpyoznamblckdjeifgh

так что это 'u'будет правильно перейти к первой (в главном порядке столбца) ненулевой записи, которая (3,1) в матричной записи; 't'перейдем к (4,1), 's'к (5,1); 'v'до (2,2) и т. д .:

   ······   
 v·      ·· 
u          ·
t          ·
s          ·
 ··      ·· 
   ······   

@EriktheOutgolfer Я наконец нашел время, чтобы добавить объяснение
Луис Мендо

1
Вау ... Я действительно думал, что вы отказались от этого, потому что вы удалили этот комментарий. : P
Эрик Outgolfer


7

R , 139 122 байт

-17 байт благодаря Джузеппе

u=utf8ToInt;`*`=rep;o=c(' '*12,'
')*7;o[u("  &3@LKWVUTSRDC5(")]=LETTERS[(13:38+u(scan(,'')))%%26+1];cat(o,sep='')

Объяснение:

o=rep(c(rep(' ',12),'
'),7) 

Строит пустую коробку с пробелами

u(" &3@LKWVUTSRDC5(")

представляет собой набор индексов для буквенных позиций, соответствующих:

c(7:9,23,24,38,51,64,76,75,87:82,68,67,53,40,27,15,16,4:6)

TIO


1
Вы никогда не используете, intToUtf8так что это посторонние байты, но если вы используете *вместо rep, вы можете сэкономить 2 байта и получить до 125 байтов
Джузеппе

1
Да, и используя младшие байты вместо печатаемых ascii, вы можете сбрить их -32за 122 байта . Вы можете создать их самостоятельно, используя cat(intToUtf8(bytes)).
Джузеппе

@Giuseppe Я был почти уверен, что уже удалил intToUtf8слишком много версий функции, я думаю. Ницца спасает все вокруг, спасибо
Аарон Хейман

6

JavaScript (Node.js) ,  121  119 байт

Сохранено 2 байта благодаря @tsh

c=>`2XYZABC
0VW5DE
U9F
T9G
S9H
0RQ5JI
2PONMLK`.replace(/./g,x=>''.padEnd(+x+1)||(B=Buffer)([65+([a,b]=B(c+x),a+b)%26]))

Попробуйте онлайн!

Как?

Bufferxc

c="H"x="B"

// extracting the ASCII codes
Buffer(c + x)  Buffer("HB")  <Buffer 48 42>

// assigning them to variables
[a, b] = Buffer(c + x)  a = 0x48 (72) and b = 0x42 (66)

// computing the ASCII code of the target letter
65 + ((a + b) % 26)  65 + (138 % 26)  65 + 8  73

// turning it back into a character
Buffer([73])  <Buffer 49>  implicitly coerced to "I" by replace()



4

R , 218 197 байт

-21 байт благодаря Джузеппе

function(t,l=letters,`*`=rep,s=" ",n="
",`~`=`[`,r=c(l~l>=t,l))cat(s*3,r~24:26,r~1:3,n,s,r~22:23,q<-s*6,r~4:5,n,r~21,u<-s*10,r~6,n,r~20,u,r~7,n,r~19,u,r~8,n,s,r~17:18,q,r~10:9,n,s*3,r~16:11,sep='')

Попробуйте онлайн!

Ungolfed:

alphasoup <- function(startlet){
  startnum <- which(l == startlet)
  rotatedletters <- c(letters[startnum:26], letters[1:(startnum -1)])[1:26]
  cat('   ',rotatedletters[24:26],rotatedletters[1:3], '\n ', 
      rotatedletters[22:23], s6 <- '      ', rotatedletters[4:5], '\n',
      rotatedletters[21], s10 <- rep(' ', 10), rotatedletters[6], '\n',
      rotatedletters[20], s10, rotatedletters[7], '\n',
      rotatedletters[19], s10, rotatedletters[8], '\n ',
      rotatedletters[17:18], s6, rotatedletters[10:9], '\n   ',
      rotatedletters[16:11],
      sep = '')
}

Создан повернутый вектор буквы и используется catдля заполнения края чаши этим вектором.


203 байта, если вы не возражаете против однострочных уродств; самое большое улучшение, вероятно, заключалось в удалении whichи использовании l>=tв качестве индекса напрямую, что стоило 12 байтов.
Джузеппе

2
198 байтов путем наложения [с ~. Это отличный ответ; В первые несколько попыток я потратил около 250 байт с гораздо более сложным подходом.
Джузеппе

Ах, это умно, я забываю о сравнении строк.
Зал CT

3

Java 11, 134 байта

c->"2XYZABC_0VW5DE_U9F_T9G_S9H_0RQ5JI_2PONMLK".chars().forEach(i->System.out.print(i<59?" ".repeat(i-47):(char)(i>90?10:(c+i)%26+65)))

Попробуйте онлайн.

136- байтовая версия с потенциалом для игры в гольф?

c->"2XYZABC_0VW5DE_U9F_T9G_S9H_0RQ5JI_2PONMLK".chars().forEach(i->System.out.printf("%"+(i<59?i-47:"")+"c",i>90?10:i<59?32:(c+i)%26+65))

Попробуйте онлайн.

Пояснение (к первому ответу)

c->                          // Method with character parameter and no return-type
  "2XYZABC_0VW5DE_U9F_T9G_S9H_0RQ5JI_2PONMLK"
                             //  Template-String
    .chars().forEach(i->     //  Loop over the unicode values of its characters:
    System.out.print(        //   Print:
     i<59?                   //    If the value is below 59 (so a digit character):
      " ".repeat(i-47)       //     Repeat a space that digit + 1 amount of times
     :(char)(i>90?           //    Else-if the value is above 90 (an underscore character):
              10             //     Print a newline
             :               //    Else:
              (c+i)          //     Add the current value and the input together
                   %26       //     Take modulo-26 of it to get the index in the alphabet
                      +65))) //     And add 65 to make it an uppercase letter

Почему бы не заменить цифры непечатаемыми? Таким образом, вы могли бы просто опуститьi-47
Воплощение невежества

@EmbodimentofIgnorance Боюсь, это не спасло бы ни одного байта. Число пробелов - 3, 1, 6 и 10. Число 10 используется три раза и составляет 2 байта в качестве символа ( \n). Так что, использую ли я непечатаемые и 3x \nс iили цифры-1 с i-47, оба имеют одинаковый счетчик байтов 134. И, к сожалению, у меня не может быть непечатного 0, иначе я мог бы использовать 2,0,5,9 вместо этого и использовать i+1для сохранения всего 1 байта.
Кевин Круйссен


2

Haskell, 127 байт

("cXYZABC aVWfDE UjF TjG SjH aRQfJI cPONMLK">>=).(?)
t?c|c>'Z'=' '<$['a'..c]|c<'!'="\n"|t<'B'=[c]|c>'Y'=t?'@'|1<2=pred t?succ c

Попробуйте онлайн!

Каждый символ в закодированной строке декодируется функцией ?в строку:

t?c                             -- 't' is the starting char,
                                -- 'c' the char from the encoded string
   |c>'Z'=' '<$['a'..c]         -- if 'c' is a lowercase letter, return some spaces
                                -- 'a': one, 'b': two, etc
   |c<'!'="\n"                  -- if 'c' is a space, return a newline
   |t<'B'=[c]                   -- if 't' is the letter A, return 'c'
   |c>'Y'=t?'@'                 -- wrap around Z
   |1<2=pred t?succ c           -- else the result is the same as starting one letter
                                -- earlier (pred t) but looking at the successor of 'c'

2

Котлин , 148 146 145 байт

Удалены лишние скобки для -2
Заменены необработанные строки для -1

{l:Char->"2XYZABC 0VW5DE U9F T9G S9H 0RQ5JI 2PONMLK".map{c->if(c>'@')((c-'A'+(l-'A'))%26+65).toChar()
else if(c>' ')" ".repeat(c-'/')
else '\n'}}

Попробуйте онлайн!


2

C # (интерактивный компилятор Visual C #) , 126 118 байт

n=>$@"   XYZABC
 VW{"",6}DE
U {"",9}F
T {"",9}G
S {"",9}H
 RQ{"",6}JI
   PONMLK".Select(b=>b<65?b:(char)((b+n)%26+65))

Сохранено 8 байтов благодаря @someone. Да, это на самом деле его имя пользователя.

Попробуйте онлайн!


Строковая интерполяция для 118 байтов . Вероятно, приемлемо вернуть массив кодов (экономя ~ 8 байт), но я не уверен.
кто-то

@ someone Ницца, забыл про интерполяцию строк
Воплощение невежества

2

TSQL-запрос, 238 байт

DECLARE @y char='G'

,@ char(91)=3;WITH C as(SELECT'5585877636333330301125255'z,8a,ascii(@y)x
UNION ALL
SELECT stuff(z,1,1,''),a+left(z,1)/3*13+left(z,1)%3-14,(x+14)%26+65FROM
C WHERE''<z)SELECT
@=stuff(stuff(@,a,1,char(x)),1+a/13*13,1,char(13))FROM
C PRINT @

Тестовая ссылка для этого ответа прервала разрывы строк и исключила пробелы. Я заменил пробелы точкой и заменил char (13) на char (13) + char (10), чтобы показать читаемый результат.

Попробуйте онлайн

Ungolfed:

DECLARE @y char='G'

-- @ is the string being printed last. 
-- @ is populated with 3 to save a byte
-- the number 3 gets replaced later
-- (this could have been any 1 digit value), 
-- @ is automatically filled with spaces, because
-- it is declared as a char(x) and assigned a value
,@ char(91)=3;
-- recursive query
WITH C as
(
-- z string containing digits for the direction of next letter
-- z should not contain 4 because it will point to same position.
-- values in z 0,1,2,3,4,5,6,7,8 can logally convert to 
-- (-1,-1),(-1,0),(-1,1),(0,-1),(0,0),(0,1),(1,-1),(1,0),(1,1)
-- a is the starting position
  SELECT'5585877636333330301125255'z,8a,ascii(@y)x
  UNION ALL
-- stuff remove first character from the z string
-- a calculate next position of the next letter
-- x cycle the input letter
  SELECT stuff(z,1,1,''),a+left(z,1)/3*13+left(z,1)%3-14,(x+14)%26+65
-- repeat recursive until long string is empty
  FROM C
  WHERE''<z
)
SELECT
-- 1st stuff replace the character to created the start of a 
--   logical line in the string @ this is where 3 gets overwritten
-- 2nd stuff replaces a character(space if coded correct) 
--  with the letter at the calculated position.
  @=stuff(stuff(@,a,1,char(x)),1+a/13*13,1,char(13))
FROM C

PRINT @

@ MickyT хорошо, спасибо за ваш отзыв, я исправлю это позже сегодня, если смогу получить доступ к db
t-clausen.dk

@MickyT это нужно исправить сейчас
t-clausen.dk

1
выглядит хорошо сейчас.
MickyT

1

PHP , 236 229 226 байт

<?=($a=ord(file_get_contents('php://stdin'))-65)?preg_replace_callback('~\w~',function($m)use($a){return chr((ord($m[0])-65+$a)%26+65);},'   XYZABC
 VW      DE
U          F
T          G
S          H
 RQ      JI
   PONMLK'):'';

Попробуйте онлайн!

Pre-гольф:

<?php
$adjust = ord(file_get_contents('php://stdin')) - 65;
echo preg_replace_callback('~\w~', function($match) use ($adjust) {
    $new = ord($match[0]) - 65;
    $new = ($new + $adjust) % 26;
    $new += 65;
    return chr($new);
}, '   XYZABC
 VW      DE
U          F
T          G
S          H
 RQ      JI
   PONMLK');

Объяснение:

Используя это, ordмы конвертируем в целое число от 0 до 255. A - 65, а Z - 90.
Используя это знание, мы берем входные данные и уменьшаем их на 65, чтобы у нас было значение корректировки.
Затем мы перебираем все символы, вызываем ordих, уменьшаем их на 65, увеличиваем их на наше значение корректировки. Используя модуль по модулю, мы возвращаемся к 0, если они превышают 26.
Затем мы снова увеличиваем их на 65 и конвертируем обратно в буквы с помощью chr.

К сожалению, php: // stdin может быть введен только один раз, поэтому нам нужно передать входные данные в функцию в нашем цикле, не позволяя нам сохранять байты, use($a)а необходимость объявлять переменную вне функции не позволяет нам чисто использовать <?=метод echo - мы должны завернуть все в гигантскую троицу.


1

C (GCC) 286 байтов

Не совсем самый короткий гольф, но он работает

#define r(a)(a+c)%26+65
#define R(a)for(i=10;i;a[--i]<33?:(a[i]=r(a[i])));
i;f(c){char*S="          ",T[]="   XYZABC\n",E[]="VW      DE\n",F[]="RQ      JI\n",B[]="   PONMLK";R(T)R(E)R(F)R(B)printf("%s %s%c%s%c\n%c%s%c\n%c%s%c\n %s%s",T,E,r(85),S,r(70),r(84),S,r(71),r(83),S,r(72),F,B);}

Попробуйте онлайн





0

Javascript (V8), 316 байт

function a(b){n="abcdefghijklmnopqrstuvwxyz".split(b);n=b+n[1]+n[0],console.log(`   ${n[23]+n[24]+n[25]+n[0]+n[1]+n[2]}\n ${n[21]+n[22]}      ${n[3]+n[4]}\n${n[20]}          ${n[5]}\n${n[19]}          ${n[6]}\n${n[18]}          ${n[7]}\n ${n[17]+n[16]}      ${n[9]+n[8]}\n   ${n[15]+n[14]+n[13]+n[12]+n[11]+n[10]}`)}

Попробуйте онлайн

Впервые попробовал код гольф. Ценю любые советы / отзывы.

Оригинальный код перед минификацией:

function a(b){
    var c = ("abcdefghijklmnopqrstuvwxyz").split(b);
    c = b+c[1]+c[0]
    console.log(`   ${c[23]+c[24]+c[25]+c[0]+c[1]+c[2]}\n ${c[21]+c[22]}      ${c[3]+c[4]}\n${c[20]}          ${c[5]}\n${c[19]}          ${c[6]}\n${c[18]}          ${c[7]}\n ${c[17]+c[16]}      ${c[9]+c[8]}\n   ${c[15]+c[14]+c[13]+c[12]+c[11]+c[10]}`)
}

Привет и добро пожаловать в PPCG. На самом деле ваше представление является фрагментом, который является недопустимым вводом / выводом. Пожалуйста, исправьте свой ответ, чтобы он был либо полной программой, либо функцией - как в вашей неминифицированной версии.
Джонатан Фрех

@ Джонатан Фреш спасибо! Будет ли этого достаточно?
Эдвин Чуа

1
Да, теперь это действительное представление.
Джонатан Фрех


0

C (gcc) , 200 198 197 байтов

-3 байта благодаря потолку.

x,z;f(c){char*y,t[27],i=0;for(c-=46;i<14;t[13+i++]=(c-i)%26+65)t[i]=(c+i)%26+65;for(i=-4;++i<4;printf("%*.*s%*.*s\n",3273>>x*3&7,x?:1,y,z,x?:1,y+2*!i+z))z="--*%"[x=abs(i)]-34,y=t+x+(x>2)+13*(i>0);}

Попробуйте онлайн!


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.