Last active
August 29, 2015 14:05
-
-
Save ydm/e9793035c6b387709988 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
# -*- coding: utf-8 -*- | |
from __future__ import print_function | |
from itertools import count | |
from math import sqrt | |
seqsum = lambda step, end: (step + end - (end % step)) * (end // step) // 2 | |
def pe001(): | |
# Твоето решение създава два списъка, а след това и множество от | |
# уникални стойности (set). Защо? Задачата се решава от аматьори с | |
# цикъл (виж ОК), а най–доброто решение е с формула (виж GREAT). | |
# Излишно е да казвам, че цикълът се изпълнява с време О(Н), докато | |
# решението с формула е О(1). | |
ok = sum([x for x in range(1000) if x % 3 == 0 or x % 5 == 0]) | |
great = seqsum(3, 999) + seqsum(5, 999) - seqsum(15, 999) | |
print('ok={}, great={}'.format(ok, great)) | |
def pe002(): | |
# Това го запомни – рекурсия използваш единствено и само когато | |
# влаганията са logN. В никакъв случай не трябва да използваш | |
# линейна рекурсия. Или поне не в Пайтън. Виж, в езици като Хаскел | |
# и (някои диалекти на) Лисп е напълно разумно, но в Пайтън – | |
# категорично не. Това решение използва ГЕНЕРАТОР. Виж в | |
# документацията. | |
def fib(end, pred): | |
a, b = 0, 1 | |
while a < end: | |
if pred(a): | |
yield a | |
a, b = b, a + b | |
print(sum(fib(4000000, lambda x: x % 2 == 0))) | |
def pe003(): | |
# Доста буквално си възприел идеята за ситото на Ератостен. Виж | |
# други имплементации, например тези на Доналд Кнут – | |
# http://www-cs-faculty.stanford.edu/~uno/programs.html . | |
pass | |
def pe004(): | |
# Брутална сила. | |
pass | |
def pe005(): | |
# Тази е добре решена, браво! | |
pass | |
def pe006(): | |
# Както и за първата, използваш брутална сила, а може много по–лесно | |
# и ефективно да бъде, ако използваш формулата. | |
# https://github.com/ydm/some-stuff-i-need-shared-between-pcs/blob/master/pe/pe006.lisp | |
pass | |
def pe007(): | |
# Ц! | |
pass | |
def pe008(): | |
# От раз става ясно, че по–добро решение от О(Н) не можеш да дадеш, | |
# защото трябва да обходиш всички цифрит в дадения ред. Какво | |
# по–просто има от това? Да използваш стр.сплит('0') е абсурдно, | |
# защото, когато пишеш код, искаш той да не е зависим по никакъв | |
# начин от входните данни. В твоя случай обаче това е точно така. | |
# Какво ще стане, ако входните ти данни имат 0 на всяка десета | |
# позиция? Алгоритъмът ти ще се провали, а това е недопустимо. | |
pass | |
def pe009(): | |
# топ() е функция, която открива горна граница за по–малкия от двата | |
# катета на правоъгълен триъгълник с даден сбор на страните а + б + | |
# ц. Оставям те сам да откриеш защо и как. Ако ти се занимава, | |
# разбира се. :) | |
s = 1000 | |
top = lambda k: int((4*k - sqrt(8*k*k)) / 4 + 1) | |
fb = lambda a, s: (2*s*a - s*s) // (2*a - 2*s) | |
for a in range(1, top(s)): | |
b = fb(a, s) | |
c = s - a - b | |
if c*c == a*a + b*b: | |
print('a={}, b={}, c={}'.format(a, b, c)) | |
break | |
def pe010(): | |
# Още едно Ц! | |
pass | |
def main(): | |
g = globals() | |
for i in count(1): | |
fn = 'pe{:03}'.format(i) | |
try: | |
f = g[fn] | |
except KeyError: | |
break | |
else: | |
print('{}: '.format(fn), end='') | |
f() | |
print() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
А така се решава задачата на С: