Решение на Пет функции от Стефан Маринов

Обратно към всички решения

Към профила на Стефан Маринов

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 16 успешни тест(а)
  • 0 неуспешни тест(а)

Код

"""Solution to the second homework problem of the 2014 FMI/python course.
Course: Python Programming, FMI, Sofia University, http://fmi.py-bg.net/
Author: Stefan Marinov, www.smarinov.com
"""
from collections import defaultdict
from functools import cmp_to_key
# Complete lowercase version of the modern Bulgarian alphabet
BULGARIAN_ALPHABET = set('абвгдежзийклмнопрстуфхцчшщъьюя')
def is_pangram(sentence):
"""Check whether `sentence` is a pangram in Bulgarian and return a bool."""
return BULGARIAN_ALPHABET == {character for character in sentence.lower()
if character in BULGARIAN_ALPHABET}
def char_histogram(text):
"""Create a character histogram of `text` and return it as a dict."""
histogram = {}
for character in text:
if character in histogram:
histogram[character] += 1
else:
histogram[character] = 1
return histogram
def sort_by(func, arguments):
"""Sort an iterable using a legacy `cmp` function converting it to keys."""
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
"""Group all `dictionary` items grouped by the types of their `keys`."""
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
"""Return a `list` of `list`s containing all anagram groups in `words`."""
groups = defaultdict(list)
for word in words:
sorted_word = ''.join(sorted([character for character in word.lower()
if character.isalpha()]))
groups[sorted_word].append(word)
return list(groups.values())

Лог от изпълнението

................
----------------------------------------------------------------------
Ran 16 tests in 0.008s

OK

История (9 версии и 10 коментара)

Стефан обнови решението на 13.03.2014 13:53 (преди над 10 години)

+import functools
+
+
+def is_pangram(sentence):
+ whole_alphabet = {char for char in 'абвгдежзийклмнопрстуфхцчшщъьюя'}
+ letters_met = {char for char in sentence.lower() if char.isalpha()}
+
+ return letters_met == whole_alphabet
+
+
+def char_histogram(text):
+ histogram = {}
+ for char in text:
+ try:
+ histogram[char] += 1
+ except KeyError:
+ histogram[char] = 1
+
+ return histogram
+
+
+def sort_by(func, arguments):
+ return sorted(arguments, key=functools.cmp_to_key(func))
+
+
+def group_by_type(dictionary):
+ groups = {}
+ for key, value in dictionary.items():
+ try:
+ groups[type(key)].update({key: value})
+ except KeyError:
+ groups[type(key)] = {key: value}
+
+ return groups
+
+
+def anagrams(words):
+ groups = {}
+ for word in words:
+ sorted_word = ''.join(sorted(word))
+ try:
+ groups[sorted_word].append(word)
+ except KeyError:
+ groups[sorted_word] = [word]
+
+ return list(groups.values())

Стефан обнови решението на 13.03.2014 15:53 (преди над 10 години)

import functools
def is_pangram(sentence):
- whole_alphabet = {char for char in 'абвгдежзийклмнопрстуфхцчшщъьюя'}
+ whole_alphabet = set('абвгдежзийклмнопрстуфхцчшщъьюя')
letters_met = {char for char in sentence.lower() if char.isalpha()}
return letters_met == whole_alphabet
def char_histogram(text):
histogram = {}
for char in text:
try:
histogram[char] += 1
except KeyError:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
return sorted(arguments, key=functools.cmp_to_key(func))
def group_by_type(dictionary):
groups = {}
for key, value in dictionary.items():
try:
groups[type(key)].update({key: value})
except KeyError:
groups[type(key)] = {key: value}
return groups
def anagrams(words):
groups = {}
for word in words:
sorted_word = ''.join(sorted(word))
try:
groups[sorted_word].append(word)
except KeyError:
groups[sorted_word] = [word]
- return list(groups.values())
+ return list(groups.values())

Стефан обнови решението на 13.03.2014 16:46 (преди над 10 години)

-import functools
+from collections import defaultdict
+from functools import cmp_to_key
def is_pangram(sentence):
whole_alphabet = set('абвгдежзийклмнопрстуфхцчшщъьюя')
letters_met = {char for char in sentence.lower() if char.isalpha()}
return letters_met == whole_alphabet
def char_histogram(text):
histogram = {}
for char in text:
try:
histogram[char] += 1
except KeyError:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
- return sorted(arguments, key=functools.cmp_to_key(func))
+ return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
- groups = {}
+ groups = defaultdict(dict)
for key, value in dictionary.items():
- try:
- groups[type(key)].update({key: value})
- except KeyError:
- groups[type(key)] = {key: value}
+ groups[type(key)].update({key: value})
return groups
def anagrams(words):
- groups = {}
+ groups = defaultdict(list)
for word in words:
- sorted_word = ''.join(sorted(word))
- try:
- groups[sorted_word].append(word)
- except KeyError:
- groups[sorted_word] = [word]
+ groups[''.join(sorted(word))].append(word)
return list(groups.values())

Стефан обнови решението на 15.03.2014 14:40 (преди над 10 години)

from collections import defaultdict
from functools import cmp_to_key
def is_pangram(sentence):
whole_alphabet = set('абвгдежзийклмнопрстуфхцчшщъьюя')
- letters_met = {char for char in sentence.lower() if char.isalpha()}
+ letters_met = {char for char in sentence.lower() if char in whole_alphabet}
return letters_met == whole_alphabet
def char_histogram(text):
histogram = {}
for char in text:
try:
histogram[char] += 1
except KeyError:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
groups = defaultdict(list)
for word in words:
- groups[''.join(sorted(word))].append(word)
+ groups[''.join(sorted(word.lower()))].append(word)
return list(groups.values())

Анаграма е дума или фраза образувана от буквите на друга дума или фраза, чрез пермутация.

  • Твоето решение не прави разлика между буква и символ
  • Операторът in е добър начин да разбереш дали нещо е в друго нещо. Изключенията са лош

Стефан обнови решението на 16.03.2014 00:42 (преди над 10 години)

from collections import defaultdict
from functools import cmp_to_key
def is_pangram(sentence):
whole_alphabet = set('абвгдежзийклмнопрстуфхцчшщъьюя')
letters_met = {char for char in sentence.lower() if char in whole_alphabet}
return letters_met == whole_alphabet
def char_histogram(text):
histogram = {}
for char in text:
try:
histogram[char] += 1
except KeyError:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
groups = defaultdict(list)
for word in words:
- groups[''.join(sorted(word.lower()))].append(word)
+ groups[''.join(filter(str.isalpha, sorted(word.lower())))].append(word)
return list(groups.values())

Стефан обнови решението на 16.03.2014 00:56 (преди над 10 години)

from collections import defaultdict
from functools import cmp_to_key
def is_pangram(sentence):
whole_alphabet = set('абвгдежзийклмнопрстуфхцчшщъьюя')
letters_met = {char for char in sentence.lower() if char in whole_alphabet}
return letters_met == whole_alphabet
def char_histogram(text):
histogram = {}
for char in text:
- try:
+ if char in histogram:
histogram[char] += 1
- except KeyError:
+ else:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
groups = defaultdict(list)
for word in words:
groups[''.join(filter(str.isalpha, sorted(word.lower())))].append(word)
return list(groups.values())

Опа, сега вече нямам изключения и анаграмите отчитат само букви за пермутациите.

Поправка: Въпросът за изключенията го преместих във форумите, за да е по-лесно достъпен и за останалите.

Стефан обнови решението на 18.03.2014 16:44 (преди над 10 години)

from collections import defaultdict
from functools import cmp_to_key
def is_pangram(sentence):
- whole_alphabet = set('абвгдежзийклмнопрстуфхцчшщъьюя')
- letters_met = {char for char in sentence.lower() if char in whole_alphabet}
+ WHOLE_ALPHABET = set('абвгдежзийклмнопрстуфхцчшщъьюя')
+ letters_met = {char for char in sentence.lower() if char in WHOLE_ALPHABET}
- return letters_met == whole_alphabet
+ return letters_met == WHOLE_ALPHABET
def char_histogram(text):
histogram = {}
for char in text:
if char in histogram:
histogram[char] += 1
else:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
groups = defaultdict(list)
for word in words:
groups[''.join(filter(str.isalpha, sorted(word.lower())))].append(word)
return list(groups.values())

По същество азбуката е константа и я обозначих по съответния начин – WHOLE_ALPHABET.

Поправка: въпросът го преместих най-отдолу, за да не се губи нишката (тук не мога да оставям нови коментари).

Стефан обнови решението на 18.03.2014 17:38 (преди над 10 години)

from collections import defaultdict
from functools import cmp_to_key
def is_pangram(sentence):
WHOLE_ALPHABET = set('абвгдежзийклмнопрстуфхцчшщъьюя')
letters_met = {char for char in sentence.lower() if char in WHOLE_ALPHABET}
return letters_met == WHOLE_ALPHABET
def char_histogram(text):
histogram = {}
for char in text:
if char in histogram:
histogram[char] += 1
else:
histogram[char] = 1
return histogram
def sort_by(func, arguments):
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
groups = defaultdict(list)
for word in words:
- groups[''.join(filter(str.isalpha, sorted(word.lower())))].append(word)
+ word_letters = [char for char in word.lower() if char.isalpha()]
+ sorted_word = ''.join(sorted(word_letters))
+ groups[sorted_word].append(word)
return list(groups.values())

Разкарах онази ужасия с filter-а в anagrams(words) за сметка на много по-четимия list comprehension. Доколкото разбрах от доста четене по темата, това е и предпочитаният начин на работа в Python.

Все пак горният ми въпрос остава: добър стил ли е константи като моята WHOLE_ALPHABET да се изкарват извън всички функции в рамките на един модул, дори да са нужни само в една от тях? Тоест, избраното от мен решение, да я декларирам най-отгоре в съответната функция е по-скоро (а) за отбягване; (б) приемливо/добро; (в) за предпочитане?

  • Какъв е смисъла да кажеш това ми е константата, не я пипай като никой не може да я ползва или види? Държат се извън функциите на места, където да са достъпни до други евентуално заинтересовани страни. В случая глобалното поле е това място.
  • вместо update с новопостроен единичен речник спокойно можеш да ползваш my_dict[key] = value
  • char е съкращение. Не ползваме съкращения в имената си

Стефан обнови решението на 19.03.2014 02:02 (преди над 10 години)

+"""Solution to the second homework problem of the 2014 FMI/python course.
+
+Course: Python Programming, FMI, Sofia University, http://fmi.py-bg.net/
+Author: Stefan Marinov, www.smarinov.com
+"""
from collections import defaultdict
from functools import cmp_to_key
+# Complete lowercase version of the modern Bulgarian alphabet
+BULGARIAN_ALPHABET = set('абвгдежзийклмнопрстуфхцчшщъьюя')
+
def is_pangram(sentence):
- WHOLE_ALPHABET = set('абвгдежзийклмнопрстуфхцчшщъьюя')
- letters_met = {char for char in sentence.lower() if char in WHOLE_ALPHABET}
+ """Check whether `sentence` is a pangram in Bulgarian and return a bool."""
+ return BULGARIAN_ALPHABET == {character for character in sentence.lower()
+ if character in BULGARIAN_ALPHABET}
- return letters_met == WHOLE_ALPHABET
-
def char_histogram(text):
+ """Create a character histogram of `text` and return it as a dict."""
histogram = {}
- for char in text:
- if char in histogram:
- histogram[char] += 1
+ for character in text:
+ if character in histogram:
+ histogram[character] += 1
else:
- histogram[char] = 1
+ histogram[character] = 1
return histogram
def sort_by(func, arguments):
+ """Sort an iterable using a legacy `cmp` function converting it to keys."""
return sorted(arguments, key=cmp_to_key(func))
def group_by_type(dictionary):
+ """Group all `dictionary` items grouped by the types of their `keys`."""
groups = defaultdict(dict)
for key, value in dictionary.items():
groups[type(key)].update({key: value})
return groups
def anagrams(words):
+ """Return a `list` of `list`s containing all anagram groups in `words`."""
groups = defaultdict(list)
for word in words:
- word_letters = [char for char in word.lower() if char.isalpha()]
- sorted_word = ''.join(sorted(word_letters))
+ sorted_word = ''.join(sorted([character for character in word.lower()
+ if character.isalpha()]))
groups[sorted_word].append(word)
return list(groups.values())

@Орлин, благодаря за пълния коментар. Ще карам точките в същия ред:

  1. Да, наистина няма смисъл. Преместих я непосредствено след import-ите и преди първата функция, като ѝ сложих един коментар и по-подходящо име.
  2. Съгласен съм и точно това правя при хистограмата, но в случая с групирането според типа не е удачно. Все пак там се търси речник с типовете за ключове и речници от самите елементи. Всеки от последните е новосъздаден речник точно веднъж (при първото срещане на типа). Ако ползвам твоето предложение там, постоянно ще презаписвам съответния елемент и ще ми остане запазена само последната стойност, което би давало верен отговор само ако има по точно един елемент от всеки тип на ключа в първоначалния речник. Малко объркано, но се надявам, че се разбра все пак. :)
  3. Съгласен съм. Оправих си всички съкратени имена на променливи, които намерих.
  4. Бонус: добавих docstrings (с малко reStructuredText) според съответните PEP-ове. :)

И още един въпрос: забележката ти за съкращенията значи ли, че името на char_histogram е (сравнително) неподходящо избрано или това важи предимно/само за променливите?