1

Тема: задача №47 з codeabbey

Задача - https://www.codeabbey.com/index/task_vi … ift-cipher
Мій код:

out = []
alph = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
alph.extend(alph)
n = list(map(int, input().split()))
k = n[1]
for i in range(n[0]):
    inp = list(input())
    while len(inp) > 0:
        x = inp[0]
        if alph.count(x) > 0:
            out.append(alph[inp.index(x) + k])
        else: out.append(x)
        inp.pop(0)
print(" ".join(out))

Допожіть знайти помилку.

2 Востаннє редагувалося koala (02.01.2019 23:40:30)

Re: задача №47 з codeabbey

Поради:
- незмінний список з літер легше робити стрічкою, аніж списком. Причому стрічка "ABCDEF..." вже є, це string.ascii_uppercase.

from string import ascii_uppercase as alph
alph *= 2

Якщо треба розібрати список на 2 значення, то для цього є така штука, як деструктуризація:

n, k = [int(x) for x in input().split()]

Якщо треба перебрати всі символи у стрічці, то її не потрібно змінювати, це можна зробити простим for:

for x in inp:

Перевірити, чи входить об'єкт у колекцію, можна оператором in замість count:

if x in alph:

І не записуйте по дві операції в рядок, хоч : та ; це дозволяють. Це збиває.

Подякували: leofun01, Eff1c2

3 Востаннє редагувалося koala (02.01.2019 23:43:03)

Re: задача №47 з codeabbey

Помилка: замість out.append(alph[inp.index(x) + k]) має бути out.append(alph[alph.index(x) - k]). І пробіл в лапках не потрібен.
Перепишіть код з урахуванням всього цього, підкажу, що іще можна виправити.

Подякували: Eff1c1

4

Re: задача №47 з codeabbey

не дивитися!
from string import ascii_uppercase as alph
n, k = map(int, input().split())
cypher = str.maketrans(alph[k:]+alph[:k], alph)
print(' '.join(input().translate(cypher) for _ in range(n)))
Подякували: Eff1c1

5 Востаннє редагувалося /KIT\ (10.01.2019 20:36:03)

Re: задача №47 з codeabbey

Мій варіант (136 байт)
o,k=map(int,input().split());b=''
while o:b+=''.join(map(lambda x:x if x in' .'else chr(65+(ord(x)-65-k)%26),input()))+' ';o-=1
print(b)
Жах (118 байт)
i=input;n,k=map(int,i().split());exec("print(end=''.join((chr(65+(ord(x)-65-k)%26),x)[x in' .']for x in i())+' ');"*n)
Подякували: Eff1c1

6 Востаннє редагувалося koala (03.01.2019 00:58:40)

Re: задача №47 з codeabbey

143, і це практично той самий код
a="ABCDEFGHIJKLMNOPQRSTUVWXYZ";n,k=map(int,input().split());print(' '.join(input().translate(str.maketrans(a[k:]+a[:k],a))for _ in range(n)))
138
a="ABCDEFGHIJKLMNOPQRSTUVWXYZ";n,k=map(int,input().split())
while n:print(input().translate(str.maketrans(a[k:]+a[:k],a)),end=' ');n-=1
128 методом пана /KIT\
n,k=map(int,input().split())
while n:print(''.join(x if x in' .'else chr(65+(ord(x)-65-k)%26) for x in input()),end=' ');n-=1

і годі вже новачка збивати, це не олімпіада

Подякували: Eff1c1

7

Re: задача №47 з codeabbey

Дуже вам дякую  :)

8 Востаннє редагувалося ping (04.01.2019 22:10:13)

Re: задача №47 з codeabbey

2 Eff1c

цікаво,  попередні задачі (до №47) Ви вже   рішили?

Прихований текст

там є кілька досить цікавих - наприклад Josephus Problem #32

9

Re: задача №47 з codeabbey

illya_martynyk - мій нік на Codeabbey. Там ж здається можна подивитися чужий профіль і які задачки розв'язані.
Мені 1ної не вистачає до 45 (follower). І, до речі, на минулому тижні я був топ 5й тижня (вирішив трішки похвалитися  :) ).
Зараз не маю часу. Тим більше терміново треба вивчити HTML, CSS i JS, а я їх взагалі не знаю :(

Подякували: ping1

10

Re: задача №47 з codeabbey

Eff1c написав:

illya_martynyk - мій нік на Codeabbey. Там ж здається можна подивитися чужий профіль і які задачки розв'язані.
Мені 1ної не вистачає до 45 (follower). І, до речі, на минулому тижні я був топ 5й тижня (вирішив трішки похвалитися  :) ).

глянув.
Ну що, красиво, гарна динаміка!

Зараз не маю часу. Тим більше терміново треба вивчити HTML, CSS i JS, а я їх взагалі не знаю :(

ну HTML, CSS - це ще куди не йшло, можна основи за тиждень вивчити .
але вивчити терміново JS ?

в будь-якому випадку - бажаю успіху!

11 Востаннє редагувалося koala (05.01.2019 10:23:56)

Re: задача №47 з codeabbey

Ну добре, все одно відпишуся. Отже, оптимізуємо ваш код за моїми порадами:

out = []
from string import ascii_uppercase as alph
alph *= 2
n, k = map(int, input().split())
for _ in range(n): #i не потрібне
    inp = input()
    for x in inp:
        if x in alph:
            out.append(alph[alph.index(x) - k])
        else: 
            out.append(x)
print(" ".join(out))

Оскільки тепер ми віднімаємо індекс, нам не потрібна подвоєна стрічка.
Крім того, в обох гілках всередині відбувається out.append, тобто їх можна об'єднати, а змінну inp, що використовується лише в одному місці, не створювати:

out = []
from string import ascii_uppercase as alph
n, k = map(int, input().split())
for _ in range(n):
    for x in input():
        out.append(alph[alph.index(x) - k] if x in alph else x)
print(" ".join(out))

Тепер додаємо трохи справжньої пітонячої магії. Конструкція for ...: ...append(...) настільки часто зустрічається, що для неї створено окрему конструкцію - генератор (а сама вона вважається антипатерном):

out = []
from string import ascii_uppercase as alph
n, k = map(int, input().split())
for _ in range(n):
    r = [alph[alph.index(x) - k] if x in alph else x for x in input()]
    out += r
print(" ".join(out))

Змінну r я залишив лише для того, щоб ви змогли побачити, як це відбувається; звісно, її можна (і треба!) прибрати.
Наступне питання - пробіли. Ви їх додаєте між кожним символом, а мають бути між фразами. Я спершу не привернув увагу до цього, це технічне, але давайте виправимо:

out = []
from string import ascii_uppercase as alph
n, k = map(int, input().split())
for _ in range(n):
    out.append(''.join(alph[alph.index(x) - k] if x in alph else x for x in input()))
print(" ".join(out))

О, знову цей антипатерн for-append!

from string import ascii_uppercase as alph
n, k = map(int, input().split())
out = [''.join(alph[alph.index(x) - k] if x in alph else x for x in input()) for _ in range(n)]
print(" ".join(out))

out вже не потрібен:

from string import ascii_uppercase as alph
n, k = map(int, input().split())
print(" ".join(''.join(alph[alph.index(x) - k] if x in alph else x for x in input()) for _ in range(n)))

Що лишається? Перевірка in та index роблять, фактично, одне й те саме - пошук в циклі. Тобто у нас тут зайвий цикл всередині. Можна замість індексу брати код символу і перевіряти, чи x літера, функцією isalpha:

from string import ascii_uppercase as alph
n, k = map(int, input().split())
print(" ".join(''.join(alph[ord(x)-ord('A')-k] if x.isalpha() else x for x in input()) for _ in range(n)))

Олімпіадний спосіб - замінити ord('A') на код (65). Крім того, можна замість alph[...] робити перетворення коду в символ функцією chr, це робить /KIT\.
А можна створити словник для заміни літер:

from string import ascii_uppercase as alph
n, k = map(int, input().split())
from_letters = alph[k:]+alph[:k] #зсув alph на k літер
d = {f:t for f,t in zip(from_letters, alph)}
print(" ".join(''.join(d.get(x,x) for x in input()) for _ in range(n)))

Звісно, змінна from_letters не потрібна; cтворення словника можна перенести всередину print, скоротивши код, але тоді він перестворюватиметься на кожній ітерації, так що лишаємо як є:

from string import ascii_uppercase as alph
n, k = map(int, input().split())
d = {f:t for f,t in zip(alph[k:]+alph[:k], alph)}
print(" ".join(''.join(d.get(x,x) for x in input()) for _ in range(n)))

Але ситуація така, що оця конструкція (словник символів + ''.join(d.get(x,x) for x in input())) теж настільки популярна, що для неї існують окремі функції maketrans (створює словник) та translate (замінює символи). Так і виходить мій код.

Подякували: Eff1c, leofun012

12

Re: задача №47 з codeabbey

Ого. Ви так детально пояснили. Дуже дякую  :)  Я все зрозумів. Ну принаймні до цього місця

koala написав:

А можна створити словник для заміни літер:

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

13

Re: задача №47 з codeabbey

Ви знаєте, коли я програмую на Python, то іде щось схоже на весь цей процес - але просто очевидні місця перетворюються на автоматі (а от неочевидні доводиться переписувати).
Що ж до словників, то ось коротке пояснення. Списки ви ж знаєте? x=l[i] - i-й елемент списку записати в x. З точки зору пам'яті іде вибір одного з елементів; а от з точки зору програміста іде перетворення індексу на значення за цим індексом. Але що, як нам захочеться перетворювати не лише послідовні числа від 0 до n, а, скажімо, лише індекси 0, 1, 2, 100000? А щоб індексами були інші об'єкти, скажімо, стрічки, щоб мав сенс вираз library["Three musceteers"]? Такі конструкції звуться асоціативними масивами, словниками і, іноді, хешами (не люблю останню назву). Як вони влаштовані всередині - зараз не важливо; головне, що вони перетворюють одне значення (індекс) на інше (збережене значення). Метод get працює схоже на [], але має другий параметр - значення, якщо такого індексу в словнику немає. Тобто {1:2,"a":100}[2] викине помилку, а {1:2,"a":100}.get(2,-1) поверне -1.

Подякували: Eff1c1