The_Ice Опубликовано 25 января, 2011 Жалоба Поделиться Опубликовано 25 января, 2011 Да, что-то после знакомства с ФЯПами, на C как то писать стало лень)))Пытался на codeforces на нем писать, но, постоянно упирался в ограничение на размер выходного файла, а вот на http://www.spoj.pl/ ограничение не такое суровое (:Хотя, довольно продолжительное время, забиваю я на программирование Ссылка на комментарий
0xDEADBEEF Опубликовано 25 января, 2011 Автор Жалоба Поделиться Опубликовано 25 января, 2011 The_IceНу мы ради великого Зеайса добавим)ICFP не пробовал? Ссылка на комментарий
The_Ice Опубликовано 25 января, 2011 Жалоба Поделиться Опубликовано 25 января, 2011 Не, не пробовал)Можно попробовать, хотя я уверен, что буду на дне турнирной таблицы - навыки растерял уже (:Просто вспомнилась фраза про хаскелл из твоего блога, вот и решил поинтересоваться о том, как дела у тебя с ним обстоят Ссылка на комментарий
0xDEADBEEF Опубликовано 26 января, 2011 Автор Жалоба Поделиться Опубликовано 26 января, 2011 ололо у меня же блог естьЕсли честно сам не помню что было там) А на Хаскелл периодически посматриваю, да только руки не доходят серьезно заняться. Ссылка на комментарий
The_Ice Опубликовано 27 января, 2011 Жалоба Поделиться Опубликовано 27 января, 2011 Разговор заставил меня вернуться к spoj.pl и я вспомнил что меня бесит в решении на haskell - это сложность уложиться в лимит времени Вроде, задача не сложная:The Next PalindromeProblem code: PALINA positive integer is called a palindrome if its representation in the decimal system is the same when read from left to right and from right to left. For a given positive integer K of not more than 1000000 digits, write the value of the smallest palindrome larger than K to output. Numbers are always displayed without leading zeros.InputThe first line contains integer t, the number of test cases. Integers K are given in the next t lines.OutputFor each K, output the smallest palindrome larger than K.ExampleInput:28082133Output:8182222Time limit: 9sSource limit: 50000BПишем первую версию программки, получаем "time limit exceeded", вторую - с тем же результатом, ... приходим к четвертой версии с использованием мемоизации и принудительной строгости примерно такого вида:module Main where{--смысл кэша:имеем Map (число, следующий палиндром)на каждой итерации смотрим: есть ли в мапе число <= нужного, но палиндромкоторого больше данного нам числа, если нет - вычисляем, если есть -возвращаем уже вычисленный палиндром -}import System.IOimport qualified Data.Map as IMapimport Control.Monad.Statetype PolMap = IMap.Map Int Inttype PolS = State PolMap Inttens = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000]-- "рабочая" рекурсивная функция функции is_palindrome_is_pali:: Int -> Int -> Bool_is_pali x n | x < 10 = True -- однозначное число - это палиндром | otherwise = x`seq`n`seq` let last_digit = x `mod` 10 first_digit = div x $! ( tens !! n) next = tailed `div` 10 tailed = mod x $! (first_digit * (tens !! n)) in if last_digit /= first_digit then False -- если первая цифра /= последней - значит не -- палиндром else if n < 3 then True -- если число 2х/3х значное, -- то нет смысла смотреть дальше else next `seq` _is_pali next $! (n-2)-- возвращает True, если переданное число - палиндромis_palindrome:: Int-> Boolis_palindrome x = x `seq` let fcnt = (fromIntegral x)::Float cnt = floor $! logBase 10 fcnt in _is_pali x $! cnt-- собственно - бэк-энд для нахождения следующего палиндромаnext_palindrome:: Int-> Intnext_palindrome x = if is_palindrome x then x else next_palindrome $! x+1-- next_palindrome с использованием кэширования вычислинных "следующих"-- палиндромовmem_next_palindrom::Int-> PolSmem_next_palindrom num = do cache <- get -- найдем максимальный вычисленный палиндром let (max_key, max_pali) = case IMap.null cache of True-> (1,2) _ -> IMap.findMax cache if num >= max_pali then do -- если переданное число больше сохраненного палиндрома, то нет -- смысла искать в кэше let next_pali = next_palindrome num put $! IMap.insert num next_pali cache -- сохраняем в кэш return next_pali else do -- функция поиска подхдящей пары в кэше: -- key должен быть меньше или равен переданному числу, а value > его let filter_foo k v = k `seq` v `seq` if k <= num && v > num then True else False filtered = IMap.toList $! IMap.filterWithKey filter_foo cache case filtered of []-> do -- если подходящих значений не найденно - вычисляем и -- добавляем в кэш let next_pali = next_palindrome num put $! IMap.insert num next_pali cache return next_pali ((_,next_pali):_) -> return next_pali -- ура, оптимизация! -- efficient next_palindrome - бэк-энд для next_palindrome с использованием кэшаeff_next_palindrome:: Int-> PolMap-> Inteff_next_palindrome num cache = evalState (mem_next_palindrom num) cachemain = do cnt' <- getLine let cnt = (read cnt')::Int cache::PolMap cache = IMap.empty input 0 = return () input n = do line <- getLine let some = (read line):: Int print $! eff_next_palindrome (some + 1) cache input $! (n-1) input cntно, по-прежнему получаем time limit exceeded И приходим к выводу, что я просто использую не самый быстрый алгоритм решения о том, является ли число палиндромом *26В итоге: --ЧСВ и засыпаю в дурацком настроении))) Конечно, по-хорошему, нужно было бы переписать на Сях и сравнить результат, но мне лень гг Ссылка на комментарий
0xDEADBEEF Опубликовано 28 января, 2011 Автор Жалоба Поделиться Опубликовано 28 января, 2011 Решение линейное. А это как-то на него не походит(#include const int MAXLEN = 1000000;char s[MAXLEN], l[MAXLEN/2], rl[MAXLEN/2];void next(){ memset(l, 0 , sizeof l); memset(rl, 0 , sizeof rl); int n = strlen(s); int m = (n & 1) ? (n+1)/2 : n/2; int i = 0; //collect polyndrom while(i l[i] = s[i]; i++; } for (int j = 0; j<=m; ++j){ rl[j] = l[m-j-1]; } for (int j = m-(n&1), c = 0; j s[c] = s[j]; } s[m] = 0;// printf("RL: %s R: %s\n",rl,s); if (strcmp(rl,s)<=0){ i--; while(i>=0){ if (l[i] != '9'){ l[i]++; break; } else { l[i] = '0'; i--; } } }// print if (i < 0) { putchar('1'); i = n; while(--i) putchar('0'); putchar('1'); } else { i = m; printf("%s", l); if (n & 1) --i; while (--i >= 0) { putchar(l[i]); } } putchar('\n'); return;}int main(){ int t; scanf("%d", &t); while(t--){ scanf("%s", s); next(); }}#include Пора наверно мутировать в хаскел-гуру... Ссылка на комментарий
The_Ice Опубликовано 29 января, 2011 Жалоба Поделиться Опубликовано 29 января, 2011 Ох уж и намучался я с решением. Судя по всему, spoj.pl тоже меня опрокинул.Твою прогу на С++ принял, а все мои на хаскелл отверг по TLE, я уже было решил плюнуть на хаскелл, коль я не умею писать на нем быстрый код, но, решил сравнить результат прог на своих данных и был и удивлен и разочарован одновременно:Итоговая версия, на которой я решил прекратить попытки аппрува на spoj.pl, работает со строками и не проверяет, является ли число палиндромом (аналог твоей на С++) и выглядит так:import Data.Charimport qualified Data.ByteString.Char8 as Bnext_num:: B.ByteString-> B.ByteStringnext_num str | B.null str = let !ret = B.pack "1" in ret | otherwise = let !last_c = digitToInt $! B.last str !headed = str `seq` B.init str in if last_c < 9 then let !ret = B.snoc headed $! intToDigit (last_c+1) in ret else let !inc_headed = next_num headed !ret = B.snoc inc_headed '0' in retnext_polindrome:: B.ByteString-> B.ByteStringnext_polindrome current = let !len = B.length current !half_len = (len `div` 2) + if odd len then 1 else 0 !half = B.take half_len current !rhalf = B.reverse half !tail_ = B.drop half_len current !even_len = if (rhalf > tail_) then let !ret = half `B.append` rhalf in ret else let !inc_half = next_num half !inc_rhalf = if (B.length inc_half > B.length half) then B.tail $! B.reverse inc_half else B.reverse inc_half !ret = inc_half `B.append` inc_rhalf in ret !half_less = B.init half !rhalf_less = B.reverse half_less !odd_len = if (rhalf_less > tail_) then let !ret = half `B.append` (B.reverse half_less) in ret else let !inc_half_raw = next_num half !inc_half = if B.length inc_half_raw > B.length half then B.init inc_half_raw else inc_half_raw !inc_rhalf = B.reverse $ B.init inc_half_raw !ret = inc_half `B.append` inc_rhalf in ret in if even len then even_len else odd_lenmain = do cnt' <- getLine let !cnt = (read cnt')::Int input 0 = return () input n = do line <- B.getLine let !dropped = B.dropWhile (=='0') line !next = next_polindrome dropped B.putStrLn next input (n-1) input cntmodule Main whereВходные данные генерились просто:Prelude> let nums = max_n:[1..max_n]Prelude> let content = unlines $ map show numsPrelude> writeFile "data" contentPrelude> let max_n = 100000Т.е. первая строка - число 100000, а все остальные - это числа от 1 до 100000 включительноПрограммы собирались такими командами:ghc --make ./Palindrome.hs -o ./palig++ -O3 ./Test.cpp -o ./testThe Glorious Glasgow Haskell Compilation System, version 6.12.1ice@desktop:~/devel/spoj/palindrom$ g++ --versiong++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5ice@desktop:~/devel/spoj/palindrom$ ghc --versionА запускались такими:$ cat ./data | ./pali > ./pali_out$ cat ./data | ./test > ./test_outТ.е. вывод программы на haskell писался в pali_out, а твоей на С++ - в test_out и diff различий не находилice@desktop:~/devel/spoj/palindrom$ echo $?0ice@desktop:~/devel/spoj/palindrom$ diff ./pali_out ./test_outНо! Самое интересное показали вот результаты вот этих команд:ice@desktop:~/devel/spoj/palindrom$ time `cat ./data | ./test > /dev/null`real 0m37.444suser 0m37.430ssys 0m0.000sice@desktop:~/devel/spoj/palindrom$ time `cat ./data | ./pali > /dev/null`real 0m2.647suser 0m2.640ssys 0m0.000sТут я начал сильно сомневаться, но вот это говорит о том, что все правильно:real 0m38.103suser 0m38.080ssys 0m0.010sice@desktop:~/devel/spoj/palindrom$ time `cat ./data | ./pali > ./pali_out`real 0m2.596suser 0m2.580ssys 0m0.010sice@desktop:~/devel/spoj/palindrom$ diff ./pali_out ./test_outice@desktop:~/devel/spoj/palindrom$ echo $?0ice@desktop:~/devel/spoj/palindrom$ time `cat ./data | ./test > ./test_out`Для того, кто на протяжении двух дней безуспешно пытался получить аппрув решения, укладывающееся в лимит времени 9 секунд и так его и не получив, это было невероятно.Оставалось только думать, что ситуация меняется при обработке чисел с 1_000_000 цифр, что и требовалось проверить, поэтому составил набор данных с БОЛЬШИМИ числами:Prelude> let min_n = 10 ^ 1000000Prelude> let max_n = min_n + 20Prelude> let nums = 20:[min_n .. max_n]Prelude> let content = unlines $ map show numsPrelude> writeFile "huge" contentPrelude>Leaving GHCi.Удалил старые результаты, на всякий пожарный:ice@desktop:~/devel/spoj/palindrom$ rm outice@desktop:~/devel/spoj/palindrom$ rm out1И, момент истины:ice@desktop:~/devel/spoj/palindrom$ time `cat ./huge | ./pali > ./pali_out`real 0m0.667suser 0m0.410ssys 0m0.290sice@desktop:~/devel/spoj/palindrom$ time `cat ./huge | ./test > ./test_out`real 0m1.351suser 0m1.010ssys 0m0.370sИ, вот с таким вот выражением лица , я осознаю, что за это время я успел и кэш прикрутить и многопоточность и все четно - я по-прежнему получаю time limit exceeded)))Более того, выявился 1 баг:-rw-r--r-- 1 ice ice 20000040 2011-01-30 00:04 pali_out-rw-r--r-- 1 ice ice 30000040 2011-01-30 00:05 test_outУчитывая, что в файле должно содержаться 20 чисел, состоящих из 1000000 цифр + 20 символов перевода строки, создается впечатление, что программа на С++ содержит багу (:строкаchar s[MAXLEN+1], l[(MAXLEN/2) + 1], rl[(MAXLEN/2)+1];решаетУшел на форум spoj.pl со злым выражением лица)UPD:Интересно то, что ленивая версия программы работает еще быстрее:import Data.Charimport qualified Data.ByteString.Lazy.Char8 as Bnext_num:: B.ByteString-> B.ByteStringnext_num str | B.null str = B.pack "1" | otherwise = let last_c = digitToInt $ B.last str headed = str `seq` B.init str in if last_c < 9 then B.snoc headed $ intToDigit (last_c+1) else let inc_headed = next_num headed in B.snoc inc_headed '0'next_polindrome:: B.ByteString-> B.ByteStringnext_polindrome current = let len = B.length current half_len = (len `div` 2) + if odd len then 1 else 0 half = B.take half_len current rhalf = B.reverse half tail_ = B.drop half_len current even_len = if (rhalf > tail_) then let ret = half `B.append` rhalf in ret else let inc_half = next_num half inc_rhalf = if (B.length inc_half > B.length half) then B.tail $ B.reverse inc_half else B.reverse inc_half in inc_half `B.append` inc_rhalf half_less = B.init half rhalf_less = B.reverse half_less odd_len = if (rhalf_less > tail_) then half `B.append` (B.reverse half_less) else let inc_half_raw = next_num half inc_half = if B.length inc_half_raw > B.length half then B.init inc_half_raw else inc_half_raw inc_rhalf = B.reverse $ B.init inc_half_raw in inc_half `B.append` inc_rhalf in if even len then even_len else odd_lenmain = do cnt' <- getLine let cnt = (read cnt')::Int content <- B.getContents let lines = take cnt $ B.lines content output [] = return () output (l:ls) = do let dropped = B.dropWhile (=='0') l B.putStrLn $ next_polindrome dropped output ls output linesmodule Main whereС такими результатами на тех же данных data:real 0m0.964suser 0m0.930ssys 0m0.020s$ time `cat ./data | ./pali_l1> /dev/null`Данные по времени на списке 800 больших чисел:Prelude> let max_n = min_n + 800Prelude> let nums = 800:[min_n .. max_n]Prelude> let foo num = do{ appendFile "huge" $! (show num)++"\n"}Prelude> mapM_ foo numsPrelude> let min_n = 10 ^ 1000000real 0m7.150suser 0m5.470ssys 0m3.230sice@desktop:~/devel/spoj/palindrom$ time `cat ./huge | ./test> /dev/null`real 0m40.444suser 0m38.760ssys 0m4.580sice@desktop:~/devel/spoj/palindrom$ time `cat ./huge | ./pali> /dev/null`real 0m19.001suser 0m17.010ssys 0m4.350sice@desktop:~/devel/spoj/palindrom$ time `cat ./huge | ./pali_l1> /dev/null`pali - это строгая версия, pali_l1 - ленивая. А я всегда старался избавиться от ленивости *28PS: извиняюсь за столь длинный пост - просто я немного озадачен результатом (: Ссылка на комментарий
Agarb Опубликовано 7 февраля, 2011 Жалоба Поделиться Опубликовано 7 февраля, 2011 Пробежался по тексту и...Если описанные в задачи действия выполнять «в лоб»...Спасибо! поправили. Ссылка на комментарий
Kenny# Опубликовано 11 февраля, 2011 Жалоба Поделиться Опубликовано 11 февраля, 2011 вопрос к организаторам.Вы не проводите открытых тренировок?Хотелось бы набраться опыта. Ссылка на комментарий
0xDEADBEEF Опубликовано 11 февраля, 2011 Автор Жалоба Поделиться Опубликовано 11 февраля, 2011 Kenny#У нас в ближайших планах открытый семинар. Следите за анонсами. Ссылка на комментарий
Kenny# Опубликовано 28 февраля, 2011 Жалоба Поделиться Опубликовано 28 февраля, 2011 Господа программисты!Прошу помощи ,совета так сказать.Не так давно, мой разум захватила идея решения задач формата ACM/ICPC .Так вот начал с acmp.ru там задачки простенькие решаемые,далее проджект эйлер ну в принципе нормально терпимо-решаемо.Затем попал наtimus и mipt вот тут подвис конкретно задачи уровня начинающих не всегда по "зубам" также учавствовал в контестах РССП (спасиб вам ) где успешно провалился.Так вот как господа прокачаться?вроде в суть задач врубаюсь но что-то не так.вижу слабые места залатываю -пробел в знаниях ,но снова неудача.Дайте что-ли направление как дальше двигаться.p.s. вроде не дурак если важно единомышленников не имею Ссылка на комментарий
danger Опубликовано 28 февраля, 2011 Жалоба Поделиться Опубликовано 28 февраля, 2011 Что я могу сказать - это то что тут главное не сдаваться. Не зря же его называют "спортивным" программированием - не будешь тренироваться, ничего не добьешься. Полтора года назад я тоже глядя на мипт, и выбирая самые легкие задачи кое-как их решал. А сейчас глядя на них кажется "че сложного то?"... в этом деле надо тренировки и развитие мозга. Решать самому(если задача не стандартная, а стандартные вскоре будут становиться все задачи) - вот главное в тренировках. Но начать же следует с алгоритмов и основ закрепляя знания на практике. \ | / \/ Ссылка на комментарий
Agarb Опубликовано 28 февраля, 2011 Жалоба Поделиться Опубликовано 28 февраля, 2011 одной из самых хороших подготовкок я считаю схему:"контест-разбор-дорешивание".Так готовятся чемпионы России (ну и мира соответственно ) на Петрозаводских сборах по СП.в контестах РССП мы тоже будем стараться придерживаться этой схемы.также есть хорошие соревнования на codeforces.ru. Там в блоге после контеста почти всегда появляется разбор, и всегда доступно дорешивание. Так же по соревнованиям opencup.ru почти всегда в сети можно найти разборы и есть дорешка. Но не только эти сайты, - это вообще распространено. И topcoder.com кста тож нужно упомянуть )))Кстати, началась серия контестов IX Открытого Кубока им. Е.В. Панкратьева по программированию (opencup.ru). Эти контесты проходят по воскресеньям и пересекаются по времени с нашими, поэтому привычное время проведения наших контестов вероятно изменится.Пожалуйста, напишите кому какое-время удобно.Например, насколько удобно будет время с 19:00 до 23:00 в будний день (напр. четверг)? Ссылка на комментарий
0xDEADBEEF Опубликовано 2 марта, 2011 Автор Жалоба Поделиться Опубликовано 2 марта, 2011 Дорешивание контестов будет доступно в четверг и пятницу (03.03 - 04.03) с 19.00 до 23.00ЗюЫю В группе вконтакте есть раздел полезных ссылок. Ссылка на комментарий
0xDEADBEEF Опубликовано 26 октября, 2011 Автор Жалоба Поделиться Опубликовано 26 октября, 2011 В субботу (29 октября 2011 года) в 17:00 в аудитории 1316 Бурятского госуниверситета (1-й корпус - за памятником Доржи Банзарову на Ул.Ранжурова, 5, 3-й этаж) состоится первая из серии открытых лекций по структурам данных и алгоритмам.Тема "Дерево отрезков - реализация и применение".Также планируется обсуждение планов развития сообщества.Приглашаются все желающие. Ссылка на комментарий
0xDEADBEEF Опубликовано 2 ноября, 2011 Автор Жалоба Поделиться Опубликовано 2 ноября, 2011 В субботу (5 ноября 2011 года) в 17:00 в аудитории №100 ВСГУТУ (1-й корпус - ул. Смолина 26, вход со двора) состоится вторая из серии открытых лекций по структурам данных и алгоритмам.Тема "RMQ (Range Minimum Query)".Приглашаются все желающие. Ссылка на комментарий
0xDEADBEEF Опубликовано 8 ноября, 2011 Автор Жалоба Поделиться Опубликовано 8 ноября, 2011 В субботу (12 ноября 2011 года) в 17:00 в аудитории №100 ВСГУТУ (1-й корпус - ул. Смолина 26, вход со двора) состоится третья из серии открытых лекций по структурам данных и алгоритмам.Тема "Programming tips and tricks".Приглашаются все желающие. Ссылка на комментарий
nonlux Опубликовано 8 ноября, 2011 Жалоба Поделиться Опубликовано 8 ноября, 2011 Идея лекций очень хорошая. Жаль на первые две не попал да и в эту субботу обломс(.Так как я не разу не был ВСГУТУ, так вход свободный?Если я пропустил три лекции как это наверстать? ведь все что я не найду в инете, будет отличаться от ваших лекций на хочется быть на той же волне. в открытые просторы сети ты их не выкладываешь? Ссылка на комментарий
0xDEADBEEF Опубликовано 8 ноября, 2011 Автор Жалоба Поделиться Опубликовано 8 ноября, 2011 nonluxВход свободный, у охранника можно спросить как пройти до аудитории, я думаю.Материалы по предыдущим лекциям можно легко найти на e-maxx.ru, по соответствующей тематике. Ссылка на комментарий
nonlux Опубликовано 8 ноября, 2011 Жалоба Поделиться Опубликовано 8 ноября, 2011 Спасибо. Ссылка на комментарий
D_Master Опубликовано 8 ноября, 2011 Жалоба Поделиться Опубликовано 8 ноября, 2011 Какова примерная продолжительность лекции? Ссылка на комментарий
0xDEADBEEF Опубликовано 8 ноября, 2011 Автор Жалоба Поделиться Опубликовано 8 ноября, 2011 D_Master1.5 - 2 часа Ссылка на комментарий
0xDEADBEEF Опубликовано 14 ноября, 2011 Автор Жалоба Поделиться Опубликовано 14 ноября, 2011 В субботу (19 ноября 2011 года) в 17:00 в аудитории №100 ВСГУТУ(1й корпус — ул. Смолина 26, вход со двора)состоится четвертая из серии открытых лекций по структурам данных и алгоритмамВведение в алгоритмы на графахПриглашаются все желающие! Ссылка на комментарий
0xDEADBEEF Опубликовано 22 ноября, 2011 Автор Жалоба Поделиться Опубликовано 22 ноября, 2011 В субботу (26 ноября 2011 года) в 17:00 в аудитории №100 ВСГУТУ(1й корпус — ул. Смолина 26, вход со двора)состоится пятая из серии открытых лекций по структурам данных и алгоритмамПоисковые алгоритмы на графах 1Приглашаются все желающие! Ссылка на комментарий
0xDEADBEEF Опубликовано 29 ноября, 2011 Автор Жалоба Поделиться Опубликовано 29 ноября, 2011 В субботу (3 декабря 2011 года) в 17:00 в аудитории №1316 БГУ (ул. Ранжурова 5, 3 этаж)состоится шестая из серии открытых лекций по структурам данных и алгоритмам.Поисковые алгоритмы на графах 2: кратчайшие пути.Приглашаются все желающие! Ссылка на комментарий
Рекомендуемые сообщения
Пожалуйста, войдите, чтобы комментировать
Вы сможете оставить комментарий после входа в
Войти