<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:_adept_</id>
  <title>dump -0f - /dev/mind</title>
  <subtitle>Баечки о мобильной связи (GSM, CDMA) и IT индустрии</subtitle>
  <author>
    <name>Dmitry Astapov</name>
  </author>
  <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/"/>
  <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom"/>
  <updated>2009-12-21T09:00:15Z</updated>
  <lj:journal userid="649412" username="_adept_" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://users.livejournal.com/_adept_/data/atom" title="dump -0f - /dev/mind"/>
  <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:100975</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/100975.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=100975"/>
    <title>Вышел третий номер "Практики функционального программирования"!</title>
    <published>2009-12-21T09:00:15Z</published>
    <updated>2009-12-21T09:00:15Z</updated>
    <category term="fprog.ru"/>
    <content type="html">Вышел в свет третий выпуск журнала «Практика функционального программирования».&lt;br /&gt;&lt;br /&gt;Коллектив авторов поздравляет вас с наступающим Новым Годом! Чтобы вам было, чем занять послепраздничные выходные (и большую часть января :), мы подготовили для вас &lt;b&gt;конкурс&lt;/b&gt;, задачи для которого обсуждались тут ранее!&lt;br /&gt;&lt;br /&gt;Кроме того, в &lt;s&gt;уникальной цирковой&lt;/s&gt; программе: рекурсивные функции тянут себя за хвост, факир прячет уходящие за горизонт фермы memcached под тонким уровнем абстракции, дрессированный верблюд превращается в кучу перьев и 1001 процесс, развенчание полиморфизма и разрезание функциональной парадигмы на части без наркоза.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a href="http://fprog.ru/2009/issue3/"&gt;&lt;img src="http://fprog.ru/images/covers/pfp2009-03.png" width="210" height="297" style="border: solid 1px #c0c0c0" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Перейти к &lt;a href="http://community.livejournal.com/fprog/5824.html"&gt;оглавлению&lt;/a&gt; номера.&lt;/center&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:100717</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/100717.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=100717"/>
    <title>Машина Дильберта</title>
    <published>2009-12-20T20:09:35Z</published>
    <updated>2009-12-20T20:19:53Z</updated>
    <category term="сын"/>
    <category term="хохмочки"/>
    <content type="html">Что такое "машина Тьюринга", знают все (или почти все).&lt;br /&gt;&lt;br /&gt;А вот что такое "машина Дильберта"? &lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;lj-embed id="3" /&gt;&lt;br /&gt;&lt;br /&gt;Календарик с Дильбертом любезно предоставлен &lt;span class='ljuser ljuser-name_kseva' lj:user='kseva' style='white-space: nowrap;'&gt;&lt;a href='http://kseva.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://kseva.livejournal.com/'&gt;&lt;b&gt;kseva&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, за что ей большое спасибо от меня и от Максима!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:100419</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/100419.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=100419"/>
    <title>Опять про Google Maps/Latitude и определение местоположения по базовым</title>
    <published>2009-12-04T15:40:58Z</published>
    <updated>2009-12-04T15:40:58Z</updated>
    <category term="gsm"/>
    <content type="html">Во-первых, спасибо всем большое за поздравления, нам было очень приятно :)&lt;br /&gt;&lt;br /&gt;А теперь - вытащу-ка я полезную информацию из комментариев.&lt;br /&gt;&lt;br /&gt;Оператор наведения &lt;span class='ljuser ljuser-name_borbelyua' lj:user='borbelyua' style='white-space: nowrap;'&gt;&lt;a href='http://borbelyua.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://borbelyua.livejournal.com/'&gt;&lt;b&gt;borbelyua&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; прислал полезную ссылку: &lt;a href="http://code.google.com/intl/ru/apis/gears/geolocation_network_protocol.html#request"&gt;http://code.google.com/intl/ru/apis/gea&lt;wbr&gt;rs/geolocation_network_protocol.html#req&lt;wbr&gt;uest&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;По ней можно ознакомиться с&amp;nbsp; API, которым, по всей видимости, пользуются Google Maps и Google Latitude.&lt;br /&gt;&lt;br /&gt;В частности, видно, что:&lt;br /&gt;1)Информация о силе сигнала и timing advance - используется.&lt;br /&gt;2)Используются как данные о базовых GSM/CDMA, так и данные о WiFi AP. Используются одновременно, в одном запросе.&lt;br /&gt;3)Можно передавать данные более чем об одной базовой =&amp;gt; используется neighbor list телефона (список сот, прописанных в текущей в качестве "соседей")&lt;br /&gt;4)В запросе можно передавать свои координаты =&amp;gt; таким образом можно обновлять/уточнять информацию в их базе&lt;br /&gt;5)В ответе возвращается точность оценки&lt;br /&gt;&lt;br /&gt;Собственно, вот и конец всем спорам, я считаю. &lt;br /&gt;&lt;br /&gt;Ну, и напоследок - забавное о жизни машин Google, снимающих streetview для Google Maps:&amp;nbsp; &lt;a href="http://googlesightseeing.com/maps?tw=772&amp;amp;p=&amp;amp;c=&amp;amp;t=h&amp;amp;hl=en&amp;amp;ll=51.135268,-114.243715&amp;amp;z=16&amp;amp;layer=c&amp;amp;cbll=51.135197,-114.243803&amp;amp;cbp=12,258.6,,1,2.12"&gt;http://googlesightseeing.com/maps?tw=772&amp;amp;p=&amp;amp;c=&amp;amp;t=h&amp;amp;hl=en&amp;amp;ll=51.135268,-114.243715&amp;amp;z=16&amp;amp;layer=c&amp;amp;cbll=51.135197,-114.243803&amp;amp;cbp=12,258.6,,1,2.12&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:100217</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/100217.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=100217"/>
    <title>Дорос до версии 1.0 :)</title>
    <published>2009-11-29T14:06:36Z</published>
    <updated>2009-11-29T14:06:36Z</updated>
    <category term="сын"/>
    <content type="html">ВНЕЗАПНО Олежке исполнился год. &lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/-vcNJjBs4RBPFHpR7o4SaA?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_5pfdFGZEn7A/SxJ-4rRC71I/AAAAAAAAA3k/YNbpJ_odnyg/s800/IMGP7049.jpg" /&gt;&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:99882</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/99882.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=99882"/>
    <title>Откуда у Google таблицы трансляции  LAC -&amp;gt; GPS coords</title>
    <published>2009-11-12T13:45:31Z</published>
    <updated>2009-11-12T20:21:32Z</updated>
    <category term="gsm"/>
    <content type="html">У Google есть сервис Latitude, который позволяет определить местоположение телефона даже в том случае, если он не оснащен GPS.&lt;br /&gt;&lt;br /&gt;Делается это при помощи трансляции уникального номера базовых станций, которые телефон "видит" в своих окрестностях, в их координаты.&lt;br /&gt;&lt;br /&gt;Откуда же у Google сведения о том, где установлены базовые? &lt;a name="cutid1"&gt;&lt;/a&gt;Я раньше писал, что я не верю, что операторы (даже в США) взяли и поделились с Google этой информацией, и скорее всего Google собрал ее самостоятельно. Возможно - с помощью тех пользователей Google Latitude, чьи телефоны оснащены GPS.&lt;br /&gt;&lt;br /&gt;А вот еще одно мнение: &lt;a href="http://3.rdrail.net/blog/cell-tower-mapping-how-google-did-it/"&gt;http://3.rdrail.net/blog/cell-tower-mapping-how-google-did-it/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Краткий пересказ: автор считает, что Google собирал соответствующую информацию в рамках проекта Google StreetView - ведь все равно они ездят (меееедленнно) по всем улицам на машине, оборудованной камерой. Так почему бы при этом не заниматься сбором информации для Latitude?&lt;br /&gt;&lt;br /&gt;Я думаю, что хороших способов много не бывает, и сбор, скорее всего, происходил и так, и так.&lt;br /&gt;&lt;br /&gt;UPD: Мое мнение по прочим вопросам из комментариев:&lt;br /&gt;1)Подобная локация по WiFi хотспотам возможна и реально используется&lt;br /&gt;2)Считать местоположение можно не по одной camped cell, а по 6 сотам из neighbour list, пересекая (теоретически посчитанные) их области покрытия. Почти наверняка при этом можно добиться лучшей точности&lt;br /&gt;3)Использовать timing advance не получится, т.к. телефон о нем не знает (если я не ошибаюсь)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:99610</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/99610.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=99610"/>
    <title>Кто про что, а я про двудольные графы</title>
    <published>2009-11-05T19:03:12Z</published>
    <updated>2009-11-05T19:03:12Z</updated>
    <category term="haskell"/>
    <content type="html">Надысь один мой френд &lt;a href="http://antilamer.livejournal.com/298055.html"&gt;написал пост&lt;/a&gt; про проверку двудольности графа на Haskell. После чего другой мой френд взял его код и &lt;a href="http://lionet.livejournal.com/44305.html"&gt;откомментировал&lt;/a&gt;. После чего третий мой френд разразился &lt;a href="http://zabivator.livejournal.com/364173.html"&gt;язвительным постом-комментарием&lt;/a&gt; на эту тему (именно в комментариях к этому посту есть эпический тред про вывод типов в PHP и иже с ними).&lt;br /&gt;&lt;br /&gt;После этого тема была &lt;a href="http://habrahabr.ru/blogs/Haskell/74164/"&gt;вытащена на Хабр&lt;/a&gt; и образцово отхабрена. &lt;br /&gt;&lt;br /&gt;Так как весь базар-вокзал - про Haskell, я тоже хочу добавить пару слов.&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Я не буду комментировать все, что написано, я скажу про сам &lt;a href="http://en.wikipedia.org/wiki/Bipartite_graph"&gt;алгоритм&lt;/a&gt;. Если б мне пришлось бы его реализовывать на Haskell, то я либо нашел бы чужой исходник и перелицевал бы его прачтически дословно. И у меня получилось бы что-то такое (т.к. исходник был бы наверняка на каком-то императивном языке):&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;br /&gt;    &lt;pre&gt;
&lt;span style="color: #0000cd;"&gt;import&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;qualified&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Data.Map&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;as&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;M&lt;/span&gt;
&lt;span style="color: #0000cd;"&gt;import&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Data.Array&lt;/span&gt;
&lt;span style="color: #0000cd;"&gt;import&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Control.Monad.State&lt;/span&gt;

&lt;span style="color: #0000cd;"&gt;type&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Graph&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Array&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Int&lt;/span&gt; [&lt;span style="color: #cd8500; font-weight: bold;"&gt;Int&lt;/span&gt;]

&lt;span style="color: #0000cd;"&gt;data&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Color&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Red&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;|&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Blue&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;deriving&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Eq&lt;/span&gt;

&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;isBipartite&lt;/span&gt; graph &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; run &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;do&lt;/span&gt;

  &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1055;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1088;&amp;#1103;&amp;#1077;&amp;#1084;, &amp;#1087;&amp;#1086;&amp;#1083;&amp;#1091;&amp;#1095;&amp;#1080;&amp;#1083;&amp;#1086;&amp;#1089;&amp;#1100; &amp;#1083;&amp;#1080; "&amp;#1076;&amp;#1074;&amp;#1091;&amp;#1076;&amp;#1086;&amp;#1083;&amp;#1100;&amp;#1085;&amp;#1086;" &amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1090;&amp;#1100; &amp;#1074;&amp;#1089;&amp;#1077; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1099; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1085;&amp;#1086;&amp;#1089;&amp;#1090;&amp;#1080; &amp;#1075;&amp;#1088;&amp;#1072;&amp;#1092;&amp;#1072;.
&lt;/span&gt;  &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1063;&amp;#1090;&amp;#1086;&amp;#1073;&amp;#1099; &amp;#1085;&amp;#1077; &amp;#1088;&amp;#1077;&amp;#1072;&amp;#1083;&amp;#1080;&amp;#1079;&amp;#1086;&amp;#1074;&amp;#1099;&amp;#1074;&amp;#1072;&amp;#1090;&amp;#1100; &amp;#1086;&amp;#1090;&amp;#1076;&amp;#1077;&amp;#1083;&amp;#1100;&amp;#1085;&amp;#1086; &amp;#1074;&amp;#1099;&amp;#1095;&amp;#1080;&amp;#1089;&amp;#1083;&amp;#1077;&amp;#1085;&amp;#1080;&amp;#1077; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1085;&amp;#1099;&amp;#1093; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1090;, &amp;#1090;&amp;#1091;&amp;#1087;&amp;#1086; &amp;#1087;&amp;#1099;&amp;#1090;&amp;#1072;&amp;#1077;&amp;#1084;&amp;#1089;&amp;#1103;
&lt;/span&gt;  &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1085;&amp;#1072;&amp;#1095;&amp;#1072;&amp;#1090;&amp;#1100; &amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1090;&amp;#1100; &amp;#1089;&amp;#1086; &amp;#1074;&amp;#1089;&amp;#1077;&amp;#1093; &amp;#1091;&amp;#1079;&amp;#1083;&amp;#1086;&amp;#1074; &amp;#1087;&amp;#1086;&amp;#1076;&amp;#1088;&amp;#1103;&amp;#1076; - &amp;#1090;&amp;#1072;&amp;#1082; &amp;#1085;&amp;#1080; &amp;#1086;&amp;#1076;&amp;#1085;&amp;#1072; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1072; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1085;&amp;#1086;&amp;#1089;&amp;#1090;&amp;#1080; &amp;#1085;&amp;#1080;&amp;#1082;&amp;#1091;&amp;#1076;&amp;#1072; &amp;#1086;&amp;#1090;
&lt;/span&gt;  &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1085;&amp;#1072;&amp;#1089; &amp;#1085;&amp;#1077; &amp;#1076;&amp;#1077;&amp;#1085;&amp;#1077;&amp;#1090;&amp;#1089;&amp;#1103;
&lt;/span&gt;  allTrue [ paint &lt;span style="color: #cd8500; font-weight: bold;"&gt;True&lt;/span&gt; node &lt;span style="color: #cd8500; font-weight: bold;"&gt;Red&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;|&lt;/span&gt; node &lt;span style="color: #b8860b;"&gt;&amp;lt;-&lt;/span&gt; indices graph ]
  &lt;span style="color: #0000cd;"&gt;where&lt;/span&gt;

    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1055;&amp;#1099;&amp;#1090;&amp;#1072;&amp;#1077;&amp;#1084;&amp;#1089;&amp;#1103; &amp;#1087;&amp;#1086;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1090;&amp;#1100; &amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083; `node' &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090;&amp;#1086;&amp;#1084; `color'. &amp;#1045;&amp;#1089;&amp;#1083;&amp;#1080; isSeed == True, &amp;#1090;&amp;#1086; &amp;#1084;&amp;#1099;
&lt;/span&gt;    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1087;&amp;#1099;&amp;#1090;&amp;#1072;&amp;#1077;&amp;#1084;&amp;#1089;&amp;#1103; &amp;#1085;&amp;#1072;&amp;#1095;&amp;#1072;&amp;#1090;&amp;#1100; &amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1090;&amp;#1100; &amp;#1086;&amp;#1076;&amp;#1085;&amp;#1091; &amp;#1080;&amp;#1079; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1090; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1085;&amp;#1086;&amp;#1089;&amp;#1090;&amp;#1080; &amp;#1075;&amp;#1088;&amp;#1072;&amp;#1092;&amp;#1072;. &amp;#1045;&amp;#1089;&amp;#1083;&amp;#1080; False - &amp;#1090;&amp;#1086; &amp;#1084;&amp;#1099;
&lt;/span&gt;    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1091;&amp;#1078;&amp;#1077; &amp;#1074;&amp;#1086;&amp;#1074;&amp;#1089;&amp;#1102; &amp;#1077;&amp;#1077; &amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1084;.
&lt;/span&gt;    paint isSeed node color &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;do&lt;/span&gt;

      &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1050;&amp;#1072;&amp;#1082;&amp;#1086;&amp;#1074; &amp;#1090;&amp;#1077;&amp;#1082;&amp;#1091;&amp;#1097;&amp;#1080;&amp;#1081; &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090; &amp;#1101;&amp;#1090;&amp;#1086;&amp;#1075;&amp;#1086; &amp;#1091;&amp;#1079;&amp;#1083;&amp;#1072;?
&lt;/span&gt;      current &lt;span style="color: #b8860b;"&gt;&amp;lt;-&lt;/span&gt; gets (&lt;span style="color: #cd8500; font-weight: bold;"&gt;M&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;.&lt;/span&gt;lookup node)
      &lt;span style="color: #0000cd;"&gt;case&lt;/span&gt; current &lt;span style="color: #0000cd;"&gt;of&lt;/span&gt;

        &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1045;&amp;#1089;&amp;#1083;&amp;#1080; &amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083; &amp;#1077;&amp;#1097;&amp;#1077; &amp;#1085;&amp;#1077; &amp;#1082;&amp;#1088;&amp;#1072;&amp;#1096;&amp;#1077;&amp;#1085; - &amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1084; &amp;#1077;&amp;#1075;&amp;#1086; &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090;&amp;#1086;&amp;#1084; `color', &amp;#1072; &amp;#1074;&amp;#1089;&amp;#1077; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1072;&amp;#1085;&amp;#1085;&amp;#1099;&amp;#1077; &amp;#1089; &amp;#1085;&amp;#1080;&amp;#1084;
&lt;/span&gt;        &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1091;&amp;#1079;&amp;#1083;&amp;#1099; &amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1084; &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090;&amp;#1086;&amp;#1084;, &amp;#1086;&amp;#1090;&amp;#1083;&amp;#1080;&amp;#1095;&amp;#1085;&amp;#1099;&amp;#1084; &amp;#1086;&amp;#1090; `color'. &amp;#1055;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1088;&amp;#1103;&amp;#1077;&amp;#1084;, &amp;#1087;&amp;#1086;&amp;#1083;&amp;#1091;&amp;#1095;&amp;#1080;&amp;#1083;&amp;#1086;&amp;#1089;&amp;#1100; &amp;#1083;&amp;#1080; &amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1080;&amp;#1090;&amp;#1100;
&lt;/span&gt;        &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1073;&amp;#1077;&amp;#1079; &amp;#1082;&amp;#1086;&amp;#1085;&amp;#1092;&amp;#1083;&amp;#1080;&amp;#1082;&amp;#1090;&amp;#1086;&amp;#1074;.
&lt;/span&gt;        &lt;span style="color: #cd8500; font-weight: bold;"&gt;Nothing&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;do&lt;/span&gt; modify (&lt;span style="color: #cd8500; font-weight: bold;"&gt;M&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;.&lt;/span&gt;insert node color)
                      allTrue [ paint &lt;span style="color: #cd8500; font-weight: bold;"&gt;False&lt;/span&gt; edge (swap color) &lt;span style="color: #b8860b;"&gt;|&lt;/span&gt; edge &lt;span style="color: #b8860b;"&gt;&amp;lt;-&lt;/span&gt; graph&lt;span style="color: #b8860b;"&gt;!&lt;/span&gt;node ]

        &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1045;&amp;#1089;&amp;#1083;&amp;#1080; &amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083; &amp;#1091;&amp;#1078;&amp;#1077; &amp;#1087;&amp;#1086;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1096;&amp;#1077;&amp;#1085;, &amp;#1072; &amp;#1084;&amp;#1099; &amp;#1087;&amp;#1099;&amp;#1090;&amp;#1072;&amp;#1083;&amp;#1080;&amp;#1089;&amp;#1100; &amp;#1085;&amp;#1072;&amp;#1095;&amp;#1072;&amp;#1090;&amp;#1100; &amp;#1089; &amp;#1085;&amp;#1077;&amp;#1075;&amp;#1086; &amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1091; - &amp;#1087;&amp;#1088;&amp;#1086;&amp;#1087;&amp;#1091;&amp;#1089;&amp;#1082;&amp;#1072;&amp;#1077;&amp;#1084; &amp;#1077;&amp;#1075;&amp;#1086;
&lt;/span&gt;        &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1045;&amp;#1089;&amp;#1083;&amp;#1080; &amp;#1078;&amp;#1077; &amp;#1085;&amp;#1072;&amp;#1084; &amp;#1074;&amp;#1089;&amp;#1090;&amp;#1088;&amp;#1077;&amp;#1090;&amp;#1080;&amp;#1083;&amp;#1089;&amp;#1103; &amp;#1087;&amp;#1086;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1096;&amp;#1077;&amp;#1085;&amp;#1099;&amp;#1081; &amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083; &amp;#1074; &amp;#1093;&amp;#1086;&amp;#1076;&amp;#1077; &amp;#1086;&amp;#1073;&amp;#1093;&amp;#1086;&amp;#1076;&amp;#1072; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1099; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1085;&amp;#1086;&amp;#1089;&amp;#1090;&amp;#1080;, 
&lt;/span&gt;        &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1087;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1088;&amp;#1080;&amp;#1084;, &amp;#1085;&amp;#1077;&amp;#1090; &amp;#1083;&amp;#1080; &amp;#1082;&amp;#1086;&amp;#1085;&amp;#1092;&amp;#1083;&amp;#1080;&amp;#1082;&amp;#1090;&amp;#1072; &amp;#1074; &amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1077;
&lt;/span&gt;        &lt;span style="color: #cd8500; font-weight: bold;"&gt;Just&lt;/span&gt; someColor &lt;span style="color: #b8860b;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;if&lt;/span&gt; isSeed &lt;span style="color: #0000cd;"&gt;then&lt;/span&gt; return &lt;span style="color: #cd8500; font-weight: bold;"&gt;True&lt;/span&gt;
                                    &lt;span style="color: #0000cd;"&gt;else&lt;/span&gt; return (color &lt;span style="color: #b8860b;"&gt;==&lt;/span&gt; someColor)

    swap &lt;span style="color: #cd8500; font-weight: bold;"&gt;Red&lt;/span&gt;  &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Blue&lt;/span&gt;
    swap &lt;span style="color: #cd8500; font-weight: bold;"&gt;Blue&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Red&lt;/span&gt;

    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1050;&amp;#1086;&amp;#1084;&amp;#1091; &amp;#1085;&amp;#1072;&amp;#1076;&amp;#1086;, &amp;#1090;&amp;#1086;&amp;#1090; &amp;#1080; &amp;#1090;&amp;#1072;&amp;#1082; &amp;#1087;&amp;#1086;&amp;#1085;&amp;#1103;&amp;#1083;, &amp;#1095;&amp;#1090;&amp;#1086; &amp;#1090;&amp;#1091;&amp;#1090; &amp;#1085;&amp;#1072;&amp;#1087;&amp;#1080;&amp;#1089;&amp;#1072;&amp;#1085;&amp;#1086;, &amp;#1072; &amp;#1086;&amp;#1089;&amp;#1090;&amp;#1072;&amp;#1083;&amp;#1100;&amp;#1085;&amp;#1099;&amp;#1077; &amp;#1085;&amp;#1072;&amp;#1076; &amp;#1101;&amp;#1090;&amp;#1080;&amp;#1084; &amp;#1085;&amp;#1077; &amp;#1088;&amp;#1077;&amp;#1092;&amp;#1083;&amp;#1077;&amp;#1082;&amp;#1089;&amp;#1080;&amp;#1088;&amp;#1091;&amp;#1102;&amp;#1090; :)
&lt;/span&gt;    run &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; flip evalState &lt;span style="color: #cd8500; font-weight: bold;"&gt;M&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;.&lt;/span&gt;empty
    allTrue actions &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; sequence actions &lt;span style="color: #b8860b;"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; return &lt;span style="color: #b8860b;"&gt;.&lt;/span&gt; and

&lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1053;&amp;#1091;, &amp;#1080; &amp;#1087;&amp;#1072;&amp;#1088;&amp;#1091; &amp;#1090;&amp;#1077;&amp;#1089;&amp;#1090;&amp;#1086;&amp;#1074;
&lt;/span&gt;&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;bipartite&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; 
  array (0,8) [(0,[1]),(1,[0,2,8]),(2,[1,3]),(3,[2,6]),(4,[5,7]),(5,[4]),(6,[3]),(7,[4,8]),(8,[1,7])]
                
&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;not_bipartite&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; 
  array (0,8) [(0,[1,2]),(1,[0,2,8]),(2,[1,3]),(3,[2,6]),(4,[5,7]),(5,[4]),(6,[3]),(7,[4,8]),(8,[1,7])]

&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;main&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;do&lt;/span&gt;
  print &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; isBipartite bipartite
  print &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; isBipartite not_bipartite&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Либо я почитал бы Википедию и реализовал бы алгоритм сам, с нуля. Тогда он получился бы в декларативном стиле, но мне бы понадобилась библиотека алгоритмов на графах:&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;br /&gt;    &lt;pre&gt;
&lt;span style="color: #0000cd;"&gt;import&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Data.Map&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;hiding&lt;/span&gt; (map)
&lt;span style="color: #0000cd;"&gt;import&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Data.Graph.Inductive&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;hiding&lt;/span&gt; (empty)

&lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1043;&amp;#1088;&amp;#1072;&amp;#1092; &amp;#1076;&amp;#1074;&amp;#1091;&amp;#1076;&amp;#1086;&amp;#1083;&amp;#1100;&amp;#1085;&amp;#1099;&amp;#1081;, &amp;#1077;&amp;#1089;&amp;#1083;&amp;#1080; &amp;#1087;&amp;#1086;&amp;#1089;&amp;#1083;&amp;#1077; &amp;#1087;&amp;#1086;&amp;#1082;&amp;#1088;&amp;#1072;&amp;#1089;&amp;#1082;&amp;#1080; &amp;#1082;&amp;#1086;&amp;#1085;&amp;#1094;&amp;#1099; &amp;#1074;&amp;#1089;&amp;#1077;&amp;#1093; &amp;#1088;&amp;#1077;&amp;#1073;&amp;#1077;&amp;#1088; &amp;#1080;&amp;#1084;&amp;#1077;&amp;#1102;&amp;#1090; &amp;#1088;&amp;#1072;&amp;#1079;&amp;#1085;&amp;#1099;&amp;#1077; &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090;&amp;#1072;
&lt;/span&gt;&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;isBipartite&lt;/span&gt; g &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; all (differentEndColors) (edges g)
  &lt;span style="color: #0000cd;"&gt;where&lt;/span&gt;
    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1062;&amp;#1074;&amp;#1077;&amp;#1090; &amp;#1091;&amp;#1079;&amp;#1083;&amp;#1072; &amp;#1093;&amp;#1088;&amp;#1072;&amp;#1085;&amp;#1080;&amp;#1090;&amp;#1089;&amp;#1103; &amp;#1074; &amp;#1072;&amp;#1089;&amp;#1089;&amp;#1086;&amp;#1094;&amp;#1080;&amp;#1072;&amp;#1090;&amp;#1080;&amp;#1074;&amp;#1085;&amp;#1086;&amp;#1084; &amp;#1084;&amp;#1072;&amp;#1089;&amp;#1089;&amp;#1080;&amp;#1074;&amp;#1077; `coloring'
&lt;/span&gt;    differentEndColors (n1,n2) &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; coloring&lt;span style="color: #b8860b;"&gt;!&lt;/span&gt;n1 &lt;span style="color: #b8860b;"&gt;/=&lt;/span&gt; coloring&lt;span style="color: #b8860b;"&gt;!&lt;/span&gt;n2

    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;{-&lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;
     &amp;#1069;&amp;#1090;&amp;#1086;&amp;#1090; &amp;#1084;&amp;#1072;&amp;#1089;&amp;#1089;&amp;#1080;&amp;#1074; &amp;#1089;&amp;#1086;&amp;#1079;&amp;#1076;&amp;#1072;&amp;#1077;&amp;#1090;&amp;#1089;&amp;#1103; &amp;#1080;&amp;#1079; &amp;#1089;&amp;#1087;&amp;#1080;&amp;#1089;&amp;#1082;&amp;#1072; [(Node, Color)], &amp;#1075;&amp;#1076;&amp;#1077; Color -
     &amp;#1101;&amp;#1090;&amp;#1086; Bool. 
     &amp;#1057;&amp;#1087;&amp;#1080;&amp;#1089;&amp;#1086;&amp;#1082; &amp;#1087;&amp;#1086;&amp;#1083;&amp;#1091;&amp;#1095;&amp;#1072;&amp;#1077;&amp;#1090;&amp;#1089;&amp;#1103; &amp;#1090;&amp;#1072;&amp;#1082;: &amp;#1089;&amp;#1085;&amp;#1072;&amp;#1095;&amp;#1072;&amp;#1083;&amp;#1072; &amp;#1086;&amp;#1087;&amp;#1088;&amp;#1077;&amp;#1076;&amp;#1077;&amp;#1083;&amp;#1103;&amp;#1077;&amp;#1084;, &amp;#1085;&amp;#1072; &amp;#1082;&amp;#1072;&amp;#1082;&amp;#1086;&amp;#1084;
     "&amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1085;&amp;#1077;" (&amp;#1074; &amp;#1076;&amp;#1077;&amp;#1088;&amp;#1077;&amp;#1074;&amp;#1077; &amp;#1087;&amp;#1086;&amp;#1080;&amp;#1089;&amp;#1082;&amp;#1072; &amp;#1074; &amp;#1096;&amp;#1080;&amp;#1088;&amp;#1080;&amp;#1085;&amp;#1091;) &amp;#1085;&amp;#1072;&amp;#1093;&amp;#1086;&amp;#1076;&amp;#1080;&amp;#1090;&amp;#1089;&amp;#1103; &amp;#1090;&amp;#1086;&amp;#1090; &amp;#1080;&amp;#1083;&amp;#1080; &amp;#1080;&amp;#1085;&amp;#1086;&amp;#1081;
     &amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083;, &amp;#1079;&amp;#1072;&amp;#1090;&amp;#1077;&amp;#1084; &amp;#1087;&amp;#1088;&amp;#1077;&amp;#1074;&amp;#1088;&amp;#1072;&amp;#1097;&amp;#1072;&amp;#1077;&amp;#1084; &amp;#1085;&amp;#1086;&amp;#1084;&amp;#1077;&amp;#1088; &amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1085;&amp;#1103; &amp;#1074; &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090;.
    -}&lt;/span&gt;
    coloring &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; fromList &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; map level2color nodes2levels

    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;{-&lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;
     &amp;#1063;&amp;#1090;&amp;#1086;&amp;#1073;&amp;#1099; &amp;#1086;&amp;#1087;&amp;#1088;&amp;#1077;&amp;#1076;&amp;#1077;&amp;#1083;&amp;#1080;&amp;#1090;&amp;#1100;, &amp;#1085;&amp;#1072; &amp;#1082;&amp;#1072;&amp;#1082;&amp;#1086;&amp;#1084; &amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1085;&amp;#1077; &amp;#1085;&amp;#1072;&amp;#1093;&amp;#1086;&amp;#1076;&amp;#1080;&amp;#1090;&amp;#1089;&amp;#1103; &amp;#1090;&amp;#1086;&amp;#1090; &amp;#1080;&amp;#1083;&amp;#1080; &amp;#1080;&amp;#1085;&amp;#1086;&amp;#1081; &amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083;:
     1)&amp;#1056;&amp;#1072;&amp;#1079;&amp;#1073;&amp;#1080;&amp;#1074;&amp;#1072;&amp;#1077;&amp;#1084; &amp;#1075;&amp;#1088;&amp;#1072;&amp;#1092; &amp;#1085;&amp;#1072; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1099; &amp;#1089;&amp;#1074;&amp;#1103;&amp;#1079;&amp;#1085;&amp;#1086;&amp;#1089;&amp;#1090;&amp;#1080; (components)
     2)&amp;#1041;&amp;#1077;&amp;#1088;&amp;#1077;&amp;#1084; &amp;#1087;&amp;#1077;&amp;#1088;&amp;#1074;&amp;#1091;&amp;#1102; &amp;#1074;&amp;#1077;&amp;#1088;&amp;#1096;&amp;#1080;&amp;#1085;&amp;#1091; &amp;#1080;&amp;#1079; &amp;#1082;&amp;#1072;&amp;#1078;&amp;#1076;&amp;#1086;&amp;#1081; &amp;#1082;&amp;#1086;&amp;#1084;&amp;#1087;&amp;#1086;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1099; (head) &amp;#1080; &amp;#1085;&amp;#1072;&amp;#1079;&amp;#1085;&amp;#1072;&amp;#1095;&amp;#1072;&amp;#1077;&amp;#1084; &amp;#1077;&amp;#1081; &amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1085;&amp;#1100; 0
     3)&amp;#1055;&amp;#1086;&amp;#1083;&amp;#1091;&amp;#1095;&amp;#1080;&amp;#1074;&amp;#1096;&amp;#1080;&amp;#1081;&amp;#1089;&amp;#1103; &amp;#1089;&amp;#1087;&amp;#1080;&amp;#1089;&amp;#1086;&amp;#1082; &amp;#1089;&amp;#1090;&amp;#1072;&amp;#1088;&amp;#1090;&amp;#1086;&amp;#1074;&amp;#1099;&amp;#1093; &amp;#1074;&amp;#1077;&amp;#1088;&amp;#1096;&amp;#1080;&amp;#1085; &amp;#1079;&amp;#1072;&amp;#1089;&amp;#1086;&amp;#1074;&amp;#1099;&amp;#1074;&amp;#1072;&amp;#1077;&amp;#1084; &amp;#1074; &amp;#1073;&amp;#1080;&amp;#1073;&amp;#1083;&amp;#1080;&amp;#1086;&amp;#1090;&amp;#1077;&amp;#1095;&amp;#1085;&amp;#1091;&amp;#1102; &amp;#1092;&amp;#1091;&amp;#1085;&amp;#1082;&amp;#1094;&amp;#1080;&amp;#1102; `leveln',
       &amp;#1082;&amp;#1086;&amp;#1090;&amp;#1086;&amp;#1088;&amp;#1072;&amp;#1103; &amp;#1074;&amp;#1099;&amp;#1095;&amp;#1080;&amp;#1089;&amp;#1083;&amp;#1103;&amp;#1077;&amp;#1090; &amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1085;&amp;#1100; &amp;#1074;&amp;#1089;&amp;#1077;&amp;#1093; &amp;#1086;&amp;#1089;&amp;#1090;&amp;#1072;&amp;#1083;&amp;#1100;&amp;#1085;&amp;#1099;&amp;#1093; &amp;#1091;&amp;#1079;&amp;#1083;&amp;#1086;&amp;#1074; &amp;#1075;&amp;#1088;&amp;#1072;&amp;#1092;&amp;#1072;
     &amp;#1042; &amp;#1088;&amp;#1077;&amp;#1079;&amp;#1091;&amp;#1083;&amp;#1100;&amp;#1090;&amp;#1072;&amp;#1090;&amp;#1077; &amp;#1087;&amp;#1086;&amp;#1083;&amp;#1091;&amp;#1095;&amp;#1072;&amp;#1077;&amp;#1084; &amp;#1089;&amp;#1087;&amp;#1080;&amp;#1089;&amp;#1086;&amp;#1082; [(&amp;#1091;&amp;#1079;&amp;#1077;&amp;#1083;, &amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1085;&amp;#1100;)]
    -}&lt;/span&gt;
    nodes2levels &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; leveln (zip (map head &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; components g) (repeat 0)) g

    &lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1045;&amp;#1089;&amp;#1083;&amp;#1080; &amp;#1091;&amp;#1088;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1085;&amp;#1100; &amp;#1085;&amp;#1077;&amp;#1095;&amp;#1077;&amp;#1090;&amp;#1085;&amp;#1099;&amp;#1081; - &amp;#1073;&amp;#1091;&amp;#1076;&amp;#1077;&amp;#1090; &amp;#1094;&amp;#1074;&amp;#1077;&amp;#1090; True, &amp;#1080;&amp;#1085;&amp;#1072;&amp;#1095;&amp;#1077; - False
&lt;/span&gt;    level2color (node,lvl) &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; (node, odd lvl)

&lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1055;&amp;#1077;&amp;#1088;&amp;#1077;&amp;#1074;&amp;#1086;&amp;#1076; &amp;#1075;&amp;#1088;&amp;#1072;&amp;#1092;&amp;#1072; &amp;#1074; &amp;#1074;&amp;#1080;&amp;#1076;, &amp;#1085;&amp;#1091;&amp;#1078;&amp;#1085;&amp;#1099;&amp;#1081; &amp;#1076;&amp;#1083;&amp;#1103; &amp;#1073;&amp;#1080;&amp;#1073;&amp;#1083;&amp;#1080;&amp;#1086;&amp;#1090;&amp;#1077;&amp;#1082;&amp;#1080;
&lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;Data.Graph.Inductive
&lt;/span&gt;&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;makeGraph&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;::&lt;/span&gt; [(&lt;span style="color: #cd8500; font-weight: bold;"&gt;Int&lt;/span&gt;,[&lt;span style="color: #cd8500; font-weight: bold;"&gt;Int&lt;/span&gt;])] &lt;span style="color: #b8860b;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;Gr&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;()&lt;/span&gt; &lt;span style="color: #cd8500; font-weight: bold;"&gt;()&lt;/span&gt;
&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;makeGraph&lt;/span&gt; g &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; mkUGraph vs es
  &lt;span style="color: #0000cd;"&gt;where&lt;/span&gt; vs &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; map fst g
        es &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; [(n1,n2) &lt;span style="color: #b8860b;"&gt;|&lt;/span&gt;  (n1,es) &lt;span style="color: #b8860b;"&gt;&amp;lt;-&lt;/span&gt; g, n2 &lt;span style="color: #b8860b;"&gt;&amp;lt;-&lt;/span&gt; es]

&lt;span style="color: #8a2be2; font-weight: bold;"&gt;-- &lt;/span&gt;&lt;span style="color: #8a2be2; font-weight: bold;"&gt;&amp;#1053;&amp;#1091;, &amp;#1080; &amp;#1087;&amp;#1072;&amp;#1088;&amp;#1091; &amp;#1090;&amp;#1077;&amp;#1089;&amp;#1090;&amp;#1086;&amp;#1074;
&lt;/span&gt;&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;bipartite&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; 
  [(0,[1]),(1,[0,2,8]),(2,[1,3]),(3,[2,6]),(4,[5,7]),(5,[4]),(6,[3]),(7,[4,8]),(8,[1,7])]
                
&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;not_bipartite&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; 
  [(0,[1,2]),(1,[0,2,8]),(2,[1,3]),(3,[2,6]),(4,[5,7]),(5,[4]),(6,[3]),(7,[4,8]),(8,[1,7])]

&lt;span style="color: #0000ee; font-weight: bold; text-decoration: underline;"&gt;main&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;=&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;do&lt;/span&gt;
  print &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; isBipartite &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; makeGraph bipartite
  print &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; isBipartite &lt;span style="color: #b8860b;"&gt;$&lt;/span&gt; makeGraph not_bipartite&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(Спасибо &lt;span class='ljuser ljuser-name_lomeo' lj:user='lomeo' style='white-space: nowrap;'&gt;&lt;a href='http://lomeo.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://lomeo.livejournal.com/'&gt;&lt;b&gt;lomeo&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; за ценные комментарии и идею поста)&lt;br /&gt;&lt;br /&gt;Вот. С монадными трансформерами, как у &lt;span class='ljuser ljuser-name_antilamer' lj:user='antilamer' style='white-space: nowrap;'&gt;&lt;a href='http://antilamer.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://antilamer.livejournal.com/'&gt;&lt;b&gt;antilamer&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; - тоже можно, просто я так не пишу. &lt;br /&gt;&lt;br /&gt;Мораль придумайте сами.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:99574</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/99574.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=99574"/>
    <title>Языки программирования в условиях, приближенных к боевым</title>
    <published>2009-11-03T22:26:25Z</published>
    <updated>2009-11-03T22:36:09Z</updated>
    <category term="request"/>
    <category term="fprog.ru"/>
    <content type="html">После выхода второго номера журнала &lt;a href="http://fprog.ru"&gt;"Практика функционального программирования"&lt;/a&gt; у меня состоялась интересная переписка с неким программистом, который очень любит писать на C.&lt;br /&gt;&lt;br /&gt;Кульминацией этой переписки стало то, что он предложил мне следующее пари: &lt;a name="cutid1"&gt;&lt;/a&gt;я формулирую простенькую задачу, после чего мы оба реализуем ее - он на С, я - на Haskell. После этого в условие вносятся небольшие коррективы (моделируем поведение требований в реальном мире), а мы вносим коррективы в наши программы. Результаты сравниваются по скорости исполнения, объему потребляемой памяти, количеству строк кода.&lt;br /&gt;&lt;br /&gt;Мой оппонент изначально был поставлен в неравные условия, т.к. я мог подобрать задачу так, чтобы ее было удобно реализовывать мне, и неудобно реализовывать ему. Впрочем, я постарался выбрать задачу так, чтобы ее решение не требовало каких-то узкоспециальных знаний. Фактически, мы занимались тем, что читали из файла и обрабатывали некую сложную структуру данных. (Детальное условие я тут не привожу, чтобы не "сбивать прицел" второй половине поста).&lt;br /&gt;&lt;br /&gt;Моя первая версия активно использовала Data.Generics и библиотечные парсеры на их основе, поэтому выиграла в размере и читаемости кода, но пролетела по объему потребляемой памяти. Впрочем, мой оппонент настолько понадеялся на мощь C, что решил не использовать библиотечный qsort, а реализовать insertion sort самостоятельно. Это самым пагубным образом сказалось на производительности (LOCs - строки кода, память - в мегабайтах, время - в секундах):&lt;br /&gt;&lt;br /&gt;   	 	&lt;table frame="VOID" rules="NONE" border="0" cellspacing="0" cols="4"&gt; 	&lt;colgroup&gt;&lt;col width="86" /&gt;&lt;col width="86" /&gt;&lt;col width="86" /&gt;&lt;col width="86" /&gt;&lt;/colgroup&gt; 	&lt;tbody&gt; 		&lt;tr&gt; 			&lt;td height="25" width="86" align="LEFT"&gt;&lt;br /&gt;&lt;/td&gt; 			&lt;td width="86" align="CENTER"&gt;&lt;strong&gt;LOCs&lt;/strong&gt;&lt;/td&gt; 			&lt;td width="86" align="CENTER"&gt;&lt;strong&gt;MEM max&lt;/strong&gt;&lt;/td&gt; 			&lt;td width="86" align="CENTER"&gt;&lt;strong&gt;Runtime, sec&lt;/strong&gt;&lt;/td&gt; 		&lt;/tr&gt; 		&lt;tr&gt; 			&lt;td height="17" align="LEFT"&gt;&lt;strong&gt;Haskell, v1&lt;/strong&gt;&lt;/td&gt; 			&lt;td sdval="72" sdnum="1033;" align="CENTER"&gt;72&lt;/td&gt; 			&lt;td sdval="580" sdnum="1033;" align="CENTER"&gt;580&lt;/td&gt; 			&lt;td sdval="88" sdnum="1033;" align="CENTER"&gt;88&lt;/td&gt; 		&lt;/tr&gt; 		&lt;tr&gt; 			&lt;td height="17" align="LEFT"&gt;&lt;strong&gt;C++, v1&lt;/strong&gt;&lt;/td&gt; 			&lt;td sdval="861" sdnum="1033;" align="CENTER"&gt;861&lt;/td&gt; 			&lt;td sdval="55" sdnum="1033;" align="CENTER"&gt;55&lt;/td&gt; 			&lt;td sdval="383" sdnum="1033;" align="CENTER"&gt;383&lt;/td&gt; 		&lt;/tr&gt; 	&lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Кроме того, выяснилось, что мой оппонент всячески "срезает углы" в погоне за производительностью. Например, функция сохранения обработанных данных в файл принимала, в числе прочих, числовой параметр, на который умножались определенные поля структуры перед сохранением - таким образом экономился один рекурсивный обход всей структуры данных.&lt;br /&gt;&lt;br /&gt;В результате я тоже решил "срезать углы", и принести красоту кода в жертву скорости. Мой же оппонент взялся за qsort, и к вторые (финальная) версии нашего кода "финишировали" с такими результатами:&lt;br /&gt;&lt;br /&gt;   	 	&lt;table frame="VOID" rules="NONE" border="0" cellspacing="0" cols="4"&gt; 	&lt;colgroup&gt;&lt;col width="86" /&gt;&lt;col width="86" /&gt;&lt;col width="86" /&gt;&lt;col width="86" /&gt;&lt;/colgroup&gt; 	&lt;tbody&gt; 		&lt;tr&gt; 			&lt;td height="17" width="86" align="LEFT"&gt;&lt;br /&gt;&lt;/td&gt; 			&lt;td width="86" align="CENTER"&gt;&lt;strong&gt;LOCs&lt;/strong&gt;&lt;/td&gt; 			&lt;td width="86" align="CENTER"&gt;&lt;strong&gt;MEM max&lt;/strong&gt;&lt;/td&gt; 			&lt;td width="86" align="CENTER"&gt;&lt;strong&gt;Runtime, sec&lt;/strong&gt;&lt;/td&gt; 		&lt;/tr&gt; 		&lt;tr&gt; 			&lt;td height="17" align="LEFT"&gt;&lt;strong&gt;Haskell, v2&lt;/strong&gt;&lt;/td&gt; 			&lt;td sdval="169" sdnum="1033;" align="CENTER"&gt;169&lt;/td&gt; 			&lt;td sdval="130" sdnum="1033;" align="CENTER"&gt;130&lt;/td&gt; 			&lt;td sdval="8" sdnum="1033;" align="CENTER"&gt;8&lt;/td&gt; 		&lt;/tr&gt; 	&lt;tr&gt; 			&lt;td height="17" align="LEFT"&gt;&lt;strong&gt;C++, v2&lt;/strong&gt;&lt;/td&gt; 			&lt;td sdval="950" sdnum="1033;" align="CENTER"&gt;950&lt;/td&gt; 			&lt;td sdval="54" sdnum="1033;" align="CENTER"&gt;54&lt;/td&gt; 			&lt;td sdval="5" sdnum="1033;" align="CENTER"&gt;5&lt;/td&gt; 		&lt;/tr&gt; 		&lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Я предполагал, что соотношение цифр будет гораздо сильнее не в пользу Haskell. Впрочем, меня по-прежнему можно было бы обвинить в предвзятом подходе к формулированию условий.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;К чему я все это веду?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Существует классическая &lt;a href="http://www.haskell.org/papers/NSWC/jfp.ps"&gt;статья&lt;/a&gt; "Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity", написанная в 1994-м году. За 15 лет многое изменилось, и, думается, многим было бы интересно прочитать подобную статью про положение дел сегодня.&lt;br /&gt;&lt;br /&gt;В связи с этим ищутся:&lt;br /&gt;1)Условия &lt;strong&gt;подходящей&lt;/strong&gt; задачи (критерии см. ниже)&lt;br /&gt;2)Желающие реализовать ее на Haskell/C+/Ocaml/Java/Scala/C#/... с тем, чтобы ваш код был нещадно сравнен с другими и опубликован для всеобщего обозрения.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid2"&gt;&lt;/a&gt;&lt;br /&gt;Q:Зачем все это делается?&lt;br /&gt;A:На других посмотреть, себя показать. В частности, чтобы люди имели возможность посмотреть на решения на других языках, и составить о них какие-то мнение.&lt;br /&gt;&lt;br /&gt;Q:Чем не устраивает &lt;a href="http://shootout.alioth.debian.org/"&gt;The Great Language Shootout&lt;/a&gt;?&lt;br /&gt;A:Тем, что там отдается предпочтение "быстрым и грязным" решениям, которые всячески "срезают углы". Во-первых, в таком стиле пишется дай бог чтобы 5% от всех программ, во-вторых, людям, не знающим язык X, строго противопоказано смотреть на решения на языке X в Language Shootout - останется превратное впечатление.&lt;br /&gt;&lt;br /&gt;Q:Как будут сравниваться решения, чтобы определить победителя?&lt;br /&gt;A:Никак, т.к. победителей не будет. Будут приведена определенная статистика по всем решениям, без выводов.&lt;br /&gt;&lt;br /&gt;Q:Какой тогда стимул участвовать?&lt;br /&gt;A:На других посмотреть, себя показать :)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Какой должна быть задача?&lt;/strong&gt;&lt;br /&gt;1)Не заточенной под конкретную ОС (т.е. "Реализовать компонент, встраеваемый в Word" или "плагин для libpam" - не катит)&lt;br /&gt;2)Не заточенной под конкретный язык/фреймворк/...  (т.е. "получить список сигнатур методов всех объектов указанной сборки .Net" - не катит)&lt;br /&gt;3)Если глубокие знания в предметной области дают решающее преимущество - это fail (т.е. "реализовать DES-CBC" - не катит)&lt;br /&gt;4)Чтобы она не была из категории "мне не нужно, чтобы плац был чистый, а нужно, чтобы вы задолбались" (т.е. "распарсить XLS-файл, не пользуясь библиотеками" - не катит)&lt;br /&gt;5)Задача не должна требовать много времени на реализацию (если это будут человеко-недели - никто за нее не возьмется)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Какой должна быть реализация?&lt;/strong&gt;&lt;br /&gt;1)Чтобы ее было не стыдно показать другим. В частности, чтобы решение на языке X не заплевали бы как кривое и неидиоматичное другие программисты, знающие язык X.&lt;br /&gt;2)Идеально было бы давать две реализации: первую с ориентиром на "красоту", "образцово-показательность" и легкость поддержки/развития кода (т.е. пишем как пример кода, который будет прилагаться к резюме :), а вторую - "грязную и быструю".&lt;br /&gt;3)Т.к. библиотеки - это неотъемлимая часть силы и популярности языка, библиотеками "общего назначения" (контейнеры, парсинг, ...) пользоваться можно и нужно&lt;br /&gt;4)Но! Решение, которое свелось к &lt;em&gt;исключительно&lt;/em&gt; к нахождению и использованию какой-то (узкоспециальной) библиотеки никому не интересно и рассматриваться не будет.&lt;br /&gt;&lt;br /&gt;Выбирать подходящее условие будет жюри, представляющее апологетов всех течений и направлений, в том числе - включающее тех, кто критически отзывался о материалах, уже вышедших в fprog.ru.&lt;br /&gt;&lt;br /&gt;Если у вас есть идея подходящией задачи и вы хотите ей поделится - напишите комментарий, а?&lt;br /&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:99157</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/99157.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=99157"/>
    <title>Трудное детство, деревянные игрушки :)</title>
    <published>2009-10-27T20:26:26Z</published>
    <updated>2009-10-30T22:41:43Z</updated>
    <category term="request"/>
    <category term="сын"/>
    <content type="html">Уважаемые френды-москвичи, а кто может купить для меня в московском инет-магазине одну штуковину (~1кг весом) и послать ее мне по почте или с проводником (т.к. найденные инет-магазины ничего никуда за пределы России высылать не хотять)? Деньги от меня up front, естественно - через WM или "быстрым переводом". Комменты скринятся&lt;br /&gt;&lt;br /&gt;UPD: тут набежала жена и сказала, что "одна штуковина" и "1 кг" - это очень мало. Оказывается, существуют Грандиозные Планы, о которых я не подозревал :) But not to worry, дело сугубо добровольное, всегда можно отказаться :)&lt;br /&gt;&lt;br /&gt;UPD2: Спасибо вам всем большое! Комментов набежало столько, что не успеваю всем ответить. Я тронут, без балды.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:98981</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/98981.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=98981"/>
    <title>Раз-два-три</title>
    <published>2009-10-26T08:51:01Z</published>
    <updated>2009-10-26T08:51:01Z</updated>
    <category term="сын"/>
    <content type="html">Старшему сыну исполнилось &lt;a name="cutid1"&gt;&lt;/a&gt;три года.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/_adept_/4046149892/" title="00006 by _adept_, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2462/4046149892_82e4fb8b97_m.jpg" alt="00006" height="240" width="180" /&gt;&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/_adept_/4046155090/" title="IMGP9070-1 by _adept_, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2765/4046155090_7785e1593f_m.jpg" alt="IMGP9070-1" height="240" width="160" /&gt;&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/14975175@N03/4038443396/"&gt;&lt;img src="http://farm4.static.flickr.com/3509/4038443396_ccfecbfc08_m.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Pic-related загадка: Макс иногда приходит ко мне и говорит: "папа! дай, я запущу на компьютере паровозик". Я открываю ему новый xterm (у меня на ноутбуке linux) и он делает ... Как вы думаете, что он делает (без помощи мышки, клавиатурой), чтобы "запустить паровозик"?</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:98601</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/98601.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=98601"/>
    <title>Второй номер "Практики функционального программирования"</title>
    <published>2009-09-28T09:50:49Z</published>
    <updated>2009-09-28T10:47:30Z</updated>
    <category term="fprog.ru"/>
    <category term="haskell"/>
    <content type="html">Вышел второй номер журнала "Практика функционального программирования" - теперь с меньшим количеством теории и большим количеством практики ;)&lt;br /&gt;&lt;br /&gt;Авторы статей: &lt;span class='ljuser ljuser-name__adept_' lj:user='_adept_' style='white-space: nowrap;'&gt;&lt;a href='http://users.livejournal.com/_adept_/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://users.livejournal.com/_adept_/'&gt;&lt;b&gt;_adept_&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name_thesz' lj:user='thesz' style='white-space: nowrap;'&gt;&lt;a href='http://thesz.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://thesz.livejournal.com/'&gt;&lt;b&gt;thesz&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name_gaperton' lj:user='gaperton' style='white-space: nowrap;'&gt;&lt;a href='http://gaperton.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://gaperton.livejournal.com/'&gt;&lt;b&gt;gaperton&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name_alexott' lj:user='alexott' style='white-space: nowrap;'&gt;&lt;a href='http://alexott.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://alexott.livejournal.com/'&gt;&lt;b&gt;alexott&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name__darkus_' lj:user='_darkus_' style='white-space: nowrap;'&gt;&lt;a href='http://users.livejournal.com/_darkus_/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://users.livejournal.com/_darkus_/'&gt;&lt;b&gt;_darkus_&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name_dmzlj' lj:user='dmzlj' style='white-space: nowrap;'&gt;&lt;a href='http://dmzlj.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://dmzlj.livejournal.com/'&gt;&lt;b&gt;dmzlj&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&amp;nbsp; и Александр Самойлович.&lt;br /&gt;&lt;br /&gt;Читаем на сайте: &lt;a href="http://fprog.ru/2009/issue2/"&gt;http://fprog.ru/2009/issue2/&lt;/a&gt;&lt;br /&gt;Обсуждаем в ЖЖ: &lt;a href="http://community.livejournal.com/fprog/3105.html"&gt;http://community.livejournal.com/fprog/3105.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:98417</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/98417.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=98417"/>
    <title>Новая атака на алгоритмы шифрования GSM - мысли вслух</title>
    <published>2009-09-15T20:08:12Z</published>
    <updated>2009-09-19T18:57:36Z</updated>
    <category term="gsm"/>
    <content type="html">Намедни известный эксперт в области информационной безопасности Karsten Nohl выступил с "программным заявлением" (см тут: &lt;a href="https://har2009.org/program/events/187.en.html"&gt;https://har2009.org/program/events/187.en.html&lt;/a&gt;). В двух словах суть его сводится к следующему: бюджетные системы для онлайн декодирования A5/1 - не за горами. &lt;br /&gt;&lt;br /&gt;Ассоциация GSM выступила с "&lt;a href="http://www.thetechherald.com/article.php/200935/4332/GSM-Alliance-downplays-seriousness-of-GSM-project"&gt;ответной речью&lt;/a&gt;". Суть ее - "уже боимся!".&lt;br /&gt;&lt;br /&gt;Я прочел выступление, и у меня &lt;a name="cutid1"&gt;&lt;/a&gt;появились вопросы и мысли. Которые я озвучу тут.&lt;br /&gt;&lt;br /&gt;1. Как правильно пишет сам Nohl, статьи про первые уязвимости в A5/1 появились чуть ли не 15 лет тому назад, но публичной демонстрации взлома A5/1 в условиях реального мира до сих пор не было. По слайдам выступления сложно это утверждать наверняка, но мне кажется, что мнение Карстена в том, что все, кому надо, ломают A5/1 втихаря и никто не делится. Мое мнение другое: чтобы реально слушать разговоры, нужно помимо собственно нахождения уязвимостей в A5/1 решить еще ряд сугубо инженерных проблем, до которым криптографам нету дела, вот они и не делают публичных демонстраций. Решил ли кто-то еще эти проблемы и воплотил ли решение в железе - вопрос открытый (см. ниже).&lt;br /&gt;&lt;br /&gt;2. После статьи 2006-го года Эли Баркана сотоварищи не было (насколько мне известно) других работ с публикацией более серьезных уязвимостей в A5/1. &lt;br /&gt;&lt;br /&gt;Что же "нарыл" коллектив Баркана? Основной их результат следующий - т.к. в GSM коррекция ошибок идет до шифрования (а надо бы наоборот), возможно определенное уменьшение пространства поиска для подбора Kc и реализация known ciphertext аттаки (т.е. при полностью пассивном прослушивании эфира) за вменяемое время с помощью предварительно вычисленных данных. &lt;br /&gt;&lt;br /&gt;Сами авторы статьи говорят, что при приеме без помех для взлома в течении 2 минут требуется 50 терабайт предвычисленных данных. В той же статье (в разделе про A5/2) пишется, что сигнал из эфира всегда идет с помехами, которые "мешают жить" алгоритму подбора ключа. Для A5/2 приведен измененный алгоритм, который способен работать в присутствии помех, но требует вдвое большего объема предвычисленных данных и двукратного увеличения времени на взлом. Для A5/1 указана возможность построения аналогичного алгоритма, но &lt;strong&gt;сам он не приведен и влияние помех на объем предвычисленных данных для A5/1 даже не оценено&lt;/strong&gt;. Будем считать, что и в этом случае нужно увеличить объем предвычисленных данных вдвое.&lt;br /&gt;&lt;br /&gt;Кроме того, процесс подбора ключа A5/1 является вероятностным - чем дольше мы слушаем и считаем, тем больше вероятность подобрать Kc. Соответственно, заявленные в статье 2 минуты - это примерное, а не гарантированное время подбора Kc.&lt;br /&gt;&lt;br /&gt;Из чтения слайдов Карстена, сайта его проекта и сайта проекта THC я так и не понял, как они "усушили" 50 терабайт (или даже 100, если считать с удвоением) из оригинальной статьи до 2 Tb. Скорее всего, т.к. речь идет о time-memory tradeoff, они используют меньше memory, но больше time, полагаясь на то, что с 2006-го года процессоры стали несколько быстрее :) Было бы неплохо получить какое-то подтверждение этому предположению.&lt;br /&gt;&lt;br /&gt;3. Но как же получить данные из эфира? Проект Карстена тут ссылается на THC и проект airprobe. А у них - результаты более чем скромные. Если я все правильно понял, то максимум, что сумели сделать энтузиасты - это при помощи Нокий&amp;nbsp; с прошивкой DHT3 записывать свои собственные разговоры, а потом их ломать. Т.е. дизайна и уж тем более реализации полноценного пишущего сканера GSM-сети у них нет.&lt;br /&gt;&lt;br /&gt;А что должен уметь полноценный сканер? Как минимум, разбираться, какие базовые вещают вокруг, на каких частотах, каким операторам они принадлежат, какие телефоны с какими TMSI (temporary IMSI) проявляют вокруг активность. Сканер должен уметь следить за разговором с указанного телефона, корректно обрабатывая переходы на другие частоты и базовые. &lt;br /&gt;&lt;br /&gt;Впрочем, если не получится сделать что-то работающее самостоятельно, подобное устройство (пишущий сканер без дешифратора) можно купить за несколько (десятков) килобаксов ;)&lt;br /&gt;&lt;br /&gt;4. Получается, чтобы построить прибор с "красной кнопкой", по нажатию на которую мы начинаем слушать "снятый" из эфира разговор по телефону Х, требуется:&lt;br /&gt;а)реализовать часть, которая разбирается с эфиром. В частности, позволяет указать, какой из TMSI соответствует нашему телефону или с помощью активных атак заставить телефоны "обнаружить" свои реальные IMSI и MSISDN (я про подобные способы писал в предыдущих постах)&lt;br /&gt;б)реализовать алгоритм подбора Kc для A5/1, хорошо работающий на реальных данных (с помехами/ошибками, пропусками и т.п.)&lt;br /&gt;в)рассчитать для него rainbow tables&lt;br /&gt;г)объединить все это в законченное работающее решение.&lt;br /&gt;&lt;br /&gt;Пока что мне кажется, что Карстен сотоварищи работают над пунктом (в). Причем я лично не думаю, что они рассчитывают rainbow tables для алгоритма, удовлетворяющего требованиям из пункта (б). Скорее всего, это таблицы для алгоритма, работающего на "идеальном шифропотоке" без искажений. По крайней мере, у них на wiki не написано обратного.&lt;br /&gt;&lt;br /&gt;Исходя из этого я думаю, что совершенно не зря нет публично известных демонстраций взлома A5/1 - хоть энтузиастами, хоть поставщиками коммерческих решений.&lt;br /&gt;&lt;br /&gt;А что думаете вы?</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:98120</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/98120.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=98120"/>
    <title>ICFPC'09: результаты</title>
    <published>2009-09-14T11:16:08Z</published>
    <updated>2009-09-14T11:16:08Z</updated>
    <category term="icfpc"/>
    <content type="html">Я &lt;s&gt;слоупок&lt;/s&gt; опять все пропустил: уже есть результаты ICFPC'09.&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ваш покорный слуга на 71-м месте из 328 участников. Учитывая все обстоятельства, я доволен.&lt;br /&gt;&lt;br /&gt;Полный список результатов лежит &lt;a href="http://icfpcontest.org/scoreboard.php"&gt;тут&lt;/a&gt;. Правда, цифры там обманчивы. В таблице приведены баллы, которые участники "выбили" в ходе соревнования на одних и тех же картах. А по окончанию соревнования судьи взяли исходники тех, кто попал в Top-10, и погоняли их у себя на каких-то других картах, которые до этого никто не видел. Финальные места определялись именно результатами вот такого "теста на выживание".&lt;br /&gt;&lt;br /&gt;Именно поэтому команда shinh вытеснила с первого места pepsiso, у которой был совершенно, казалось бы, недостижимый отрыв в 300 очков от всех остальных. Жалко, что полные результаты перестановок в первой десятке не выложили :(&lt;br /&gt;&lt;br /&gt;Из интересного:&lt;br /&gt;* Победитель писал на C++, второе место - на Java, судейский приз - неизвестно, победитель lighning round - на OCaml.&lt;br /&gt;* Второе  место  - команда THIRTEEN - из Харькова&lt;br /&gt;* Не написано, почему приз судейских симпатий ушел команде "when i was 4 years old i was maimed by a giant pig", но не исключено, что именно за название :)&lt;br /&gt;* Победу в lightning round-е взял широко известный в узких кругах Алексей Щепин (человек-команда jabber.ru), с чем я его от души и поздравляю :)&lt;br /&gt;&lt;br /&gt;Ждем в следующем году схватку между jabber.ru и THIRTEEN за первое место :)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:97900</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/97900.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=97900"/>
    <title>"You have unofficially advanced to Round 2"</title>
    <published>2009-09-12T20:52:30Z</published>
    <updated>2009-09-12T20:52:30Z</updated>
    <category term="codejam"/>
    <content type="html">Раунд 1А был в 4 часа утра, и я, естественно, его пропустил. В раунде 1B сделал первых две задачи полностью, благо они решались "в лоб", а третью не успел дописать :(&lt;br /&gt;&lt;br /&gt;Обидно, она была самой интересной. &lt;br /&gt;&lt;br /&gt;Пришло письмо из гугла о том, что %SUBJ%. Непонятно только, почему unofficially</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:97574</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/97574.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=97574"/>
    <title>Удивительное рядом :)</title>
    <published>2009-09-11T17:05:26Z</published>
    <updated>2009-09-11T17:05:26Z</updated>
    <content type="html">Я ожидал, что статьи на mobile-review вызовут комментарии, которые можно будет условно разделить на следующие категории:&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"Прочитал. Очень интересно"&lt;/li&gt;&lt;li&gt;"Прочитал. Ничего не понял"&lt;/li&gt;&lt;li&gt;"Прочитал. Нафига про это писать, и так все понятно?!"&lt;/li&gt;&lt;li&gt;"Прочитал. Автор - идиот: ...."&lt;/li&gt;&lt;/ul&gt;Все вышеперечисленные категории реально присуствуют. Но! Есть достаточно много комметариев вида:&lt;br /&gt;&lt;br /&gt;"Прочитал. Статья явно рекламная!"&lt;br /&gt;&lt;br /&gt;Шановна редакцiя, я у шоцi. Что ж я там рекламирую-то?&lt;br /&gt;&lt;br /&gt;PS&lt;br /&gt;Сами обсуждения:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://forum.mobile-review.com//showthread.php?t=68753"&gt;http://forum.mobile-review.com//showthread.php?t=68753&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://forum.mobile-review.com//showthread.php?t=68641"&gt;http://forum.mobile-review.com//showthread.php?t=68641&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://forum.mobile-review.com//showthread.php?t=68863"&gt;http://forum.mobile-review.com//showthread.php?t=68863&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:97354</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/97354.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=97354"/>
    <title>Кто где был и глобальная корреляция геолокационных данных</title>
    <published>2009-09-09T11:44:13Z</published>
    <updated>2009-09-09T11:44:13Z</updated>
    <category term="gsm"/>
    <content type="html">Вопрос от &lt;span class='ljuser ljuser-name_malx' lj:user='malx' style='white-space: nowrap;'&gt;&lt;a href='http://malx.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://malx.livejournal.com/'&gt;&lt;b&gt;malx&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; : &lt;i&gt;"&lt;a href="http://jeffjonas.typepad.com/jeff_jonas/2009/08/your-movements-speak-for-themselves-spacetime-travel-data-is-analytic-superfood.html"&gt;http://jeffjonas.typepad.com/jeff_j&lt;wbr&gt;onas/2009/08/your-movements-speak-for-th&lt;wbr&gt;emselves-spacetime-travel-data-is-analyt&lt;wbr&gt;ic-superfood.html&lt;/a&gt;&lt;br /&gt;что скажешь про такое вероятное будущее? :)"&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Про будущее не скажу, скажу про текст по указанной ссылке. &lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Два основных "системных" пробоя в изложении:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Цитата&lt;/strong&gt;: "Every call, text message, email and data transfer handled by your mobile device creates a transaction with your space-time coordinate (to roughly 60 meters accuracy if there are three cell towers in range)"&lt;br /&gt;&lt;strong&gt;Перевод&lt;/strong&gt;: "Любой звонок, SMS, email или передача данных при помощи мобильного устройства оставляет (в недрах оператора) запись о ваших пространственно-временных координатах (с точностью до 60 метров, если вы находитесь в зоне покрытия трех базовых станций)".&lt;br /&gt;&lt;strong&gt;Лажи&lt;/strong&gt;: 1)Упоминание трех базовых говорит, что автор имеет в виду "триангуляцию по базовым", о которой я уже писал стопятьсот раз&lt;br /&gt;2)В записях учета стоимости (а речь явно о них) как правило остается упоминание о &lt;strong&gt;одной&lt;/strong&gt; базовой. Той, которая начала обслуживать соотв. событие. Если это был звонок, и вы сидели в автомобиле, то, пока вы ездите в зоне обслуживания одного коммутатора (а это очень большая область) никто не будет генерировать доп. информацию о том, на какие базовые переключается ваше обслуживание.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Цитата&lt;/strong&gt;: "Got a Blackberry?&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Every few minutes, it sends a heartbeat, creating a transaction whether you are using the phone or not."&lt;br /&gt;&lt;strong&gt;Перевод&lt;/strong&gt;: "Телефоны с Blackberry раз в одну-две минуты посылают 'пинг', о чем остается запись у оператора. Не важно, используете ли вы в это момент телефон по назанчению или нет - это все равно происходит"&lt;br /&gt;&lt;strong&gt;Лажа&lt;/strong&gt;: основным техническим преимуществом Blackberry по сравнению с комбинацией "телефон + почтовый клиент + IMAP-idle или POP pull" является как раз то, что мобильному устройству не надо поллить ящик - по приходу новой почты сервер сделает push. Плюс ко всему, подобное "пингование" ело бы аккумулятор, как свинья помои. Соотвественно, хоть я и не спец в Blackbery, я готов дать зуб, что никакого heartbeat телефоны Blackberry не посылают.&lt;br /&gt;&lt;br /&gt;Что интересно, ближе к концу статьи автор говорит, что "если вам удасться найти место на Земле, где на многие мили вокруг есть только одна базовая, и поселиться там, то вы будете в бОльшей безопасности [относительно определения вашего местоположения]". Т.е. мое предположение о том, что автор имеет очень мало инфы о том, какая информация о положении абонента сохраняется и где, подтверждается.&lt;br /&gt;&lt;br /&gt;Все прочее, описанное в статье (использование хитромудрых рассчетов для корреляции данных о перемещении людей, выявление клик и кластеров, делание далеко идущих выводов) - теоретически возможно. Но есть одно "но".&lt;br /&gt;&lt;br /&gt;Перед многими операторами (и сервисными компаниями в других областях деятельности) уже сейчас стоит задача коррелировать друг с другом разные записи о активности их собственных клиентов (а не "всех людей вообще"). Например, соотносить заказ рингтона с GPRS-сессией, в которй он был скачан.&lt;br /&gt;&lt;br /&gt;Но в большей части случаев компании этого не делают. Потому как: 1)сложно; 2)дорого; 3)сложно; 4)дорого; 5)вложения не оправдывают результаты. И мне &lt;em&gt;кажется&lt;/em&gt;, что на сегодняшний день потенциальная отдача от подобной аналитики в глобальных масштабах никак не может оправдать затраты на создание соответствующих вычислительных средств. И слова автора о том, что "кто-то уже сейчас может загрузить это все в Amazon S3, запустить кучу процессов на Amazon EC2 и поиметь результат на блюдечке с голубой каемочкой" - это не более, чем фигура речи и сгущение красок.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:97201</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/97201.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=97201"/>
    <title>Стоит ли ноль нескольких миллионов?</title>
    <published>2009-09-08T20:51:15Z</published>
    <updated>2009-09-08T20:51:15Z</updated>
    <content type="html">Вопрос от &lt;span class='ljuser ljuser-name_crazy_daemon' lj:user='crazy_daemon' style='white-space: nowrap;'&gt;&lt;a href='http://crazy-daemon.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://crazy-daemon.livejournal.com/'&gt;&lt;b&gt;crazy_daemon&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;: "&lt;i&gt;Увидел информацию, что с 14 октября начнется переход на европейскую систему нумерации.&lt;br /&gt;И &lt;a href="http://www.gipsh.com/2009/09/europe-number/" nofollow="nofollow"&gt;тут&lt;/a&gt; увидел следующее:&lt;br /&gt;&lt;q&gt;Ориентировочная стоимость внедрения новой нумерации для одного оператора – десятки млн. гривен.&lt;/q&gt;&lt;br /&gt;&lt;br /&gt;Ну и собственно вопрос оттуда же:&lt;br /&gt;&lt;q&gt;А откуда у этой суммы ноги растут? т.е. на что должны операторы потратиться при переходе на нули?&lt;/q&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;Я не буду считать чужие деньги, но я попытаюсь перечислить то, что реально надо сделать при переходе на новую нумерацию:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Переделать все рекламные материалы (бигборды, листовки в магазинах, рекламу по ТВ)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Переделать все продажные материалы (стартовые пакеты и вкладываемые в них книжечки и т.п.)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Отдельно провести информирование абонентов о изменении правил набора через наружную рекламу, SMS-ы, анонсы на разных IVR, операторов в call center&lt;/li&gt;&lt;li&gt;Переписать сообщения на всех автоинформаторах, которые что-то говорят про номер&lt;/li&gt;&lt;li&gt;Придумать и реализовать "защиту от дурака", который будет пытаться набирать по-старому. Как минимум, чтобы его не зачарджили по много килобаксов за минуту&lt;/li&gt;&lt;li&gt;Организовать работу с абонентами, которые придут в фирменные салоны с просьбами помочь с содержимым адресной книги, перенестройкой услуг и т.п.&lt;/li&gt;&lt;li&gt;Внести изменения в процедуры управления номерным планом сети, переделать роутинг, опирающийся на номера (а в мобильной сети полно вещей, которые хотят по номеру телефона выяснить номер HLR-а, например).&lt;/li&gt;&lt;li&gt;Перенастроить все "очевидные" информационные системы, которые хоть как-то анализируют префикс телефонного номера: биллинг, сбор записей учета стоимости, управление услугами, интерконнект, борьба с мошенничеством, разнообразные сервисные платформы, предоставляющие дополнительные услуги (голосовая почта, перевод денег, USSD-запросы на управление услугами и т.п.). Изменения, думаю, будут распадаться на несколько типовых категорий, например:&amp;nbsp; префикс номера где-то анализируется на предмет "свой номер - чужой номер"; префикс номера преобразуется во что-то (название бренда, например); введеный пользователем номер валидируется, и в том числе проверяется его префикс; звонкам на номера с определенным префиксом назначена какая-то цена; префикс номера поставлен в соответствие какой-то другой информации.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Провести аудит всех прочих информационных систем на предмет того, не надо ли вносить в них какие-то изменения.&lt;/li&gt;&lt;li&gt;Если в каких-то информационных системах нельзя произвести соотв. изменения с помощью переконфигурации, и нужны дополнительные разработки - заказать их (т.е. написать спеки, запросить изменения, получить их, протестировать и установить) или сделать какие-то (временные или постоянные) костыли&lt;/li&gt;&lt;li&gt;Прошерстить все внутренние нормативные документы и исправить там места, касающиеся номеров (а таких будет дофига и больше)&lt;/li&gt;&lt;li&gt;Приготовиться провести изменения данных о номерной емкости во всех информационных системах компании, в HLR-ах, в базах сервисных платформ и т.п.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Построить или выделить тестовый фрагмент сети (если его еще нет), на котором отработать все необходимые изменения в core network&lt;/li&gt;&lt;li&gt;С его же помощью протестировать, по возможности, все измененные информационные системы&lt;/li&gt;&lt;li&gt;Разработать (многостраничную) процедуру перехода на новую нумерацию.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Протестировать ее&lt;/li&gt;&lt;li&gt;Разработать процедуру отката процедуры перехода, если вдруг в ходе перехода что-то пойдет не так&lt;/li&gt;&lt;li&gt;Протестировать ее&lt;/li&gt;&lt;li&gt;Скоординироваться с другими операторами на предмет проведения межоператорских тестов (интерконнект, роуминг)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Провести их&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Скоординировать кучу народа для проведения собственно перехода (как правило, в ночь на день D)&lt;/li&gt;&lt;li&gt;Провести переход (возможно - несколько раз, если с первого раза что-то не срослось)&lt;/li&gt;&lt;li&gt;В авральном режиме разгрести последствия какой-то фигни, о которой, невзирая на все предосторожности, все забыли, и она "выстрелила" после перехода&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Через DMS залить абонентам новые настройки MMS, VoiceMail (если надо) или проинформировать их SMS-ами о том, что это требуется&lt;/li&gt;&lt;li&gt;Принять шквал звонков в callcenter от тех, кто, невзирая на шум в СМИ, все проспал&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Фактически, объем работ в худшем случае будет сравним с запуском небольшого мобильного оператора. Потянет ли это на лимон баксов? Вполне может быть.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:96846</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/96846.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=96846"/>
    <title>А в это время в замке у шефа ...</title>
    <published>2009-09-08T18:20:44Z</published>
    <updated>2009-09-08T18:20:44Z</updated>
    <category term="gsm"/>
    <category term="pr"/>
    <content type="html">Еще один небольшой апгрейд ЧСВ: серия статей, построенная на базе обобщенного и переработанного материала отсюда и из &lt;a href="http://pro-gsm.info"&gt;http://pro-gsm.info&lt;/a&gt; начала выходить на &lt;a href="http://mobile-review.com"&gt;http://mobile-review.com&lt;/a&gt;:&lt;br /&gt;* &lt;a href="http://mobile-review.com/articles/2009/sim-clon.shtml"&gt;http://mobile-review.com/articles/2009/sim-clon.shtml&lt;/a&gt;&lt;br /&gt;* &lt;a href="http://mobile-review.com/articles/2009/triangulation.shtml"&gt;http://mobile-review.com/articles/2009/triangulation.shtml&lt;/a&gt;&lt;br /&gt;* &lt;a href="http://mobile-review.com/articles/2009/eaves-dropping.shtml"&gt;http://mobile-review.com/articles/2009/eaves-dropping.shtml&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Темы, как видите, старые, а контент - новый. Еще пять статей в очереди на публикацию.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:96600</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/96600.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=96600"/>
    <title>Почему плохо ходят SMS-ы?</title>
    <published>2009-09-07T20:59:16Z</published>
    <updated>2009-09-08T20:56:00Z</updated>
    <category term="gsm"/>
    <content type="html">Отвечаю на вопрос: "&lt;i&gt;Мне часто приходится писать смс в другую страну (из Украины в Белоруссию и обратно), и я замечаю, что иногда (один-два дня в неделю) они доходят очень плохо: нет отчёта о доставке на протяжении часа-двух днём, или смс задерживаются, а потом приходят все кучей.&lt;br /&gt;&lt;br /&gt;Также заметил, что новое смс может "спровоцировать" доставку, и все предыдущие будут доставлены вместе с ним. &lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ночью бывает нормальная связь до 2 часов, а после этого - все новые смс не доставляются, или доставляются уже утром. Иногда (редко) есть отчёт о доставке, а смс не доходит.&lt;br /&gt;&lt;br /&gt;Со звонками проблем нет вообще, всё соединяется сразу, но это дорого и не так удобно.&lt;br /&gt;&lt;br /&gt;Если это важно, то в Украине оператор Киевстар, а в Белоруссии Velcom. Впрочем, примерно аналогичная картина и с Билайном у нас - Life у них.&lt;br /&gt;&lt;br /&gt;С чем это всё может быть связано? Как найти причину, и кто поможет решить вопрос?&lt;/i&gt;"&lt;br /&gt;&lt;br /&gt;Попробую ответить.&lt;br /&gt;&lt;br /&gt;Я уже когда-то писал о том, как устроены "внутренности" системы доставки SMS - почитать об этом можно тут: &lt;a href="http://users.livejournal.com/_adept_/77752.html"&gt;http://users.livejournal.com/_adept_/77752.html&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Краткий пересказ:&lt;br /&gt;1)С мобильного телефона (пусть будет Билайн) отсылается SMS. Он попадает на SMSC Билайна.&lt;br /&gt;2)SMSC Билайна смотрит, что получатель у нас - клиент белорусского Life. SMSC контачит базу абонентов (HLR) белорусского Life и спрашивает:"где ошивается такой-то оболтус?". На что HLR отвечает: "ошивается он в зоне нашего коммутатора #13".&lt;br /&gt;3)SMSC Билайна контачит коммутатор #13 белорусского Life и говорит: "доставляй SMS"&lt;br /&gt;4)Коммутатор доставляет SMS. В обратном порядке начинают передаваться подтверждения о доставке.&lt;br /&gt;&lt;br /&gt;Если на шаге (2) получен ответ о том, что абонента нет в сети, то SMSC Билайна говорит HLR-у Life: "когда появится, пни меня". После регистрации абонента в сети немедленно срабатывает уведомление и происходит попытка доставки.&lt;br /&gt;&lt;br /&gt;Если облом происходит на шаге (4), то SMSC будет повторять доставку в соответствии со своими настройками (как правило, увеличивая паузы между попытками). В процессе SMSC всегда готов принять "встречное предложение" - если HLR Life скажет ему, что теперь уже снова можно пытаться доставлять, то SMSC это и сделает. Впрочем, сбои при доставке SMS "живому" абоненту в работающей сети редко имеют системный характер.&lt;br /&gt;&lt;br /&gt;Что же происходит у автора вопроса? Точно утверждать сложно, но самым вероятным предположением выглядит такое: у получателя SMS-ок банально &lt;strong&gt;заканчивается место в SMS inbox на телефоне&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;При этом происходит следующее: при попытке доставки очередного SMS телефон получателя говорит: "в меня больше не лезет". Информация об этом доставляется SMSC Билайна, который переходит в режим "будем пытаться еще через какое-то время". Кроме того, по стандарту телефон получателя &lt;strong&gt;может&lt;/strong&gt; (насколько я помню, не &lt;strong&gt;обязан&lt;/strong&gt;) после появления места в inbox уведомить HLR своей сети, который, в свою очередь, уведомит все SMSC, которые "подписались" на получение информации об этом событии.&lt;br /&gt;&lt;br /&gt;Похоже, что уведомление об очистке inbox либо не генерируется, либо SMSC сети отправителя не информируется об этом событии. Кроме того, иногда абонент просто спит (указано, что проблемы начинаются ночью) и очищает inbox только к утру. &lt;br /&gt;&lt;br /&gt;Так как SMSC сети отправителя не получает информации, что уже можно повторять доставку, он делает это сам только по истечении определенного таймаута. Так как речь идет о доставке в чужую сеть, сигнальный траффик тоже может быть платным, и SMSC может быть настроен таким образом, чтобы не пытаться слишком часто - например, не чаще раза в несколько часов.&lt;br /&gt;&lt;br /&gt;Допустим, было послано несколько SMS-ов. При доставке первого (второго, третьего, ... N-ного) выяснилось, что inbox полон, и все они стали в очередь на retry. В это время получатель почистил inbox. Дальше происходит одно из двух:&lt;br /&gt;1)Либо приходит еще одна SMS-ка, которая сходу доставляется и запускает процесс доставки все накопленной очереди&lt;br /&gt;2)Проходит несколько часов, одна из SMS-ок доставляется при retry и запускает процесс доставки всей очереди.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ИМХО, очень похоже на описание симптомов из вопроса&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Напоследок хотелось бы добавить пару слов про SMS inbox. Не знаю, как сейчас, а раньше он мог быть только на SIM-карте (т.к. SIM рулит процессом приема SMS-ов) и размер его был достаточно скромным - например, 16 позиций. Конечно, телефоны достаточно быстро научились копировать SMS-ки из памяти SIM-карты в память телефона прозрачным для пользователя образом, но прием SMS-ов все равно происходил в SMS inbox на SIM-карте, используемый как буффер. Кроме того, в SMS inbox на SIM-карте могли помещаться SMS-ки, помеченные пользователем как "saved SMS", "keep on SIM SMS" и т.п. (конкретные слова могут отличаться в зависимости от модели телефона).&lt;br /&gt;&lt;br /&gt;Дальше - мои домыслы. Если у человека на телефоне/SIM-карте SMS inbox размером в 16 позиций, и 15 из них заняты сохраненными SMS-ами, то шансы получить "inbox full" при активной переписке по SMS достаточно велики. Если после этого не отправляется уведомление о появлении места в inbox (а оно появляется, когда телефон сам копирует SMS из inbox в свою память), то может возникать спонтанное "залипание" SMS-диалога. Впрочем, я не дам зуб, что этот сценарий реально может реализоваться в реальной жизни.&lt;br /&gt;&lt;br /&gt;PS&lt;br /&gt;Disclaimer. Я не настоящий сварщик, я просто &lt;s&gt;нашел на стройке маску&lt;/s&gt; много читал про то, как устроен SMSC. Я никогда их не настраивал и не эксплуатировал лично, хотя и много общался с теми, кто это делает. Я знаю, что меня читают люди, у которых есть непосредственный опыт борьбы с SMSC - поругайте версию, а?&lt;br /&gt;&lt;br /&gt;UPD&lt;br /&gt;Даже если у вас телефон, в который влазит 100500 тыщь SMS, прием их все равно ведется в SMS inbox, который находится на SIM-карте, а телефон непосредственно после приема вычитывает их оттуда и размещает в своей необъятной памяти.&lt;br /&gt;&lt;br /&gt;UPD2&lt;br /&gt;Еще одна реалистичная версия из комментария &lt;span class='ljuser ljuser-name_magicprinc' lj:user='magicprinc' style='white-space: nowrap;'&gt;&lt;a href='http://magicprinc.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://magicprinc.livejournal.com/'&gt;&lt;b&gt;magicprinc&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;:&lt;br /&gt;"1) У MSC есть ограничение на количество алертов и вам его не достается т.е. абонент появляется в сети, а ваш смсц не уведомляют - поэтому он пробует через некоторое время сам по retry timeout&lt;br /&gt;2) количество узлов сети растет, а квалификация сотрудников падает - где-то что-то недопрописано (маршруты, разрешения)"&lt;br /&gt;&lt;br /&gt;UPD3&lt;br /&gt;От &lt;span class='ljuser ljuser-name_qwe13' lj:user='qwe13' style='white-space: nowrap;'&gt;&lt;a href='http://qwe13.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://qwe13.livejournal.com/'&gt;&lt;b&gt;qwe13&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;: "Хех, все совсем забыли про GPRS. Думаю не у многих операторов есть Gs. Как следствие при активной пердачи данных over GPRS абонент не отвечает на пейджинг через "CS". По окончанию передачи GPRS данных абонент ничего не знает о том, что его ждут смски, как врочем VLR тоже не знает, что абонент появился в сети.&lt;br /&gt;&lt;br /&gt;Итого смски доходят тогда, когда абонента позвонит/отправит sms или когда входящая смска поймает его не за активной пердачей данных."</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:96414</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/96414.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=96414"/>
    <title>99 баллов :)</title>
    <published>2009-09-05T18:06:05Z</published>
    <updated>2009-09-05T18:06:05Z</updated>
    <category term="codejam"/>
    <content type="html">Прошел квалификацию, выбил 99 из 99 баллов.&lt;br /&gt;&lt;br /&gt;Что приятно - во всех задачах сдавал самую первую заработавшую версию кода, в том числе и для large set. Впрочем, это скорее везение или уровень задач.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:96032</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/96032.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=96032"/>
    <title>Google Code Jam'09 - Qualification Round</title>
    <published>2009-09-03T13:19:34Z</published>
    <updated>2009-09-05T18:04:48Z</updated>
    <category term="codejam"/>
    <content type="html">Кстати, до конца квалификационного раунда Google Code Jam'09 осталось 11 часов. Учитывая, что задачки там - часа на полтора в общей сложности, еще не поздно зарегистрироваться и поучаствовать. &lt;a href="http://code.google.com/codejam"&gt;http://code.google.com/codejam&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;PS: если кто участвует: скажите, какой у вас там ник</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:95899</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/95899.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=95899"/>
    <title>Он сказал: "поехали!"</title>
    <published>2009-08-17T19:02:14Z</published>
    <updated>2009-08-18T08:45:41Z</updated>
    <category term="работа"/>
    <category term="баечки"/>
    <content type="html">Он - это &lt;a href="http://company.mts.com.ua/rus/press_releases.php?news_id=3532"&gt;пресс-релиз&lt;/a&gt;. На самом деле, там еще есть пару мелких углов, но вписывать прибавку к EXP и ЧСВ можно уже сейчас. Я там собирал требования, писал кучи документов, мигрировал данные и интегрировал все добро в одну кучу. &lt;s&gt;Вот какой я молодец&lt;/s&gt;&lt;br /&gt;&lt;br /&gt;Впрочем, не обошлось без казусов. &lt;a name="cutid1"&gt;&lt;/a&gt; Некие бравые ребята написали на PL/SQL пакетик процедур, и, натурально, вставили его в Oracle. Другие бравые ребята взяли программу на C#.Net и давай оттуда эти процедуры использовать.&lt;br /&gt;&lt;br /&gt;В тестовом окружении (Oracle 8.1.7) - все шикарно. В промышленном (Oracle 9i) - не выходит каменный цветок. Лишь только пытаешься вызвать какую-то процедуру - Оракл тут же говорит ORA-03113, end-of-file on communication channel. И закрывает соединение со своей стороны.&lt;br /&gt;&lt;br /&gt;При этом с того же самого компьютера можно подключиться к базе при помощи sqlplus, вызвать искомую процедуру и получить результат. Без всяких ошибок. Хоть раз, хоть десять.&lt;br /&gt;&lt;br /&gt;Разработчики на PL/SQL, естественно, тут же воспряли духом - ага, баг не у нас, оказывается! Только толку от этого знания немного - надо же, чтобы в конце-концов все заработало и в приложении на C#.Net.&lt;br /&gt;&lt;br /&gt;Разработчики на C# говорят: это все потому, что мы ходим через ODBC. Однако фиг - утилита ODBC Test, написанная (судя по виду GUI) еще во времена Windows 3.1, замечательным образом вызывает процедуры через ODBC.&lt;br /&gt;&lt;br /&gt;Тогда разработчики на C# говорят: это все потому, что мы все переписали и теперь работаем через OleDb. Надо поставить ораклового клиента и использовать ODP.NET оттуда. Поставили. Однако фиг - как падало, так и падает. Причем, только с Oracle 9i - с 8.1.7 по-прежнему все хорошо.&lt;br /&gt;&lt;br /&gt;Тогда разработчики на C# говорят: это у вас фиговый Оракл. Но их посылают в сад, так как "у меня нет для вас другого Оракла, товарищ Жуков".&lt;br /&gt;&lt;br /&gt;Параллельно все участники процесса насилуют Google в поисках других товарищей по несчастью. Классик говорил: "если любишь заглядывать в бездну, помни, что бездна может заглянуть в тебя". Так и происходит: гугл приносит мешок рассказов о том, как по всему земному шару люди бьются лбом об стену с ORA-03113.&lt;br /&gt;&lt;br /&gt;Типичные истории звучат примерно так: "Мы тут написали софтину на C#.NET, которая ходит в оракл. С версией 9i и ODP 9.0.1.3.1 все было хоршо, но потом мы обновили ODP до 9.0.1.3.3 и началось - ORA-03113 через пол-часа работы. Мы два месяца плясали с отладчиками, и поняли: у нас на клиентской стороне connection pool, а Оракл со своей стороны временами закрывает соединения по тайм-ауту. В пуле они не инвалидируются, и когда такое соединение выбирается для выполнения запроса, возникает ORA-03113. Мы не можем убрать пул (все тормозит) и не можем убрать отключение по тайм-ауту (требование безопасности). Более того - мы откатили ODP, но проблема осталась! Помогите!". Читаешь, и понимаешь, что у нас еще не все так плохо :)&lt;br /&gt;&lt;br /&gt;Хоть у нас все и падает сразу и пул явно ни при чем - попробовали поиграться с его отключением или параметрами. А вот фиг.&lt;br /&gt;&lt;br /&gt;В конце-концов разработчики на C# говорят: "Мы сдаемся! К вам едет "мистер Вульф, который решает пробемы" (Криминальное чтиво).". Приезжает человек, который занимается исключительно troubleshooting-ом разной неведаной фигни.&lt;br /&gt;&lt;br /&gt;Человек целый день колдует с компилятором C# и кучей разных библиотек и в конце-концов говорит: "я не знаю, что бы это значило, но факт таков - если я до вызова процедуры сделаю хотя бы один select, то все работает хорошо". Проверяем - натурально, так оно и есть. Может, дело в каких-то миллисекундных паузах? Нет, расставленные по коду паузы не помогают.&lt;br /&gt;&lt;br /&gt;Пляски с бубном продолжаются еще день, но без особого результата. В конце-концов принимается волевое решение о том, что код на C# должен после открытия соединения сделать "select table_name from all_tables where owner=current_user" и вычитать первый элемент рекордсета.&lt;br /&gt;&lt;br /&gt;И все начинает работать без сучка и задоринки. &lt;a href="http://img1.liveinternet.ru/images/attach/b/3/21/431/21431138__x_1e3d35d4.jpg"&gt;Мораль&lt;/a&gt; придумайте сами.&lt;br /&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:95693</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/95693.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=95693"/>
    <title>SmartSIM, TurboSIM, YesSIM и другие устройства для "разлочки" телефонов</title>
    <published>2009-08-06T08:45:14Z</published>
    <updated>2009-08-06T08:46:26Z</updated>
    <category term="gsm"/>
    <content type="html">Отвечаю на вопрос из &lt;a href="http://users.livejournal.com/_adept_/90746.html"&gt;пункта приема вопросов&lt;/a&gt;: "&lt;i&gt;В интернете обильно продаются всяческие "i-SmartSim SIM Card Unlock Attachment for Nokia and Most Other Cell Phones", стоят от 5 USD. Обычно выглядит как плёночка с чипом, вставляемая между симкой и телефоном. Знакомый мой одну такую купил, и говорит, что в самом деле смог использовать привязанный iPhone с SIMкой другого оператора.&lt;br /&gt;Как это может работать?&lt;/i&gt;"&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;a href="http://www.gsmgods.net/index.php/pl_PL,details,id_pr,4326,menu_mode,categories.html"&gt;&lt;img src="http://gsmgods.net/multicom/pimg/turbo_sim_400.jpg" alt="" style="float: right;" width="200" /&gt;&lt;/a&gt;Поиск по названию этих продуктов в основном выдает либо сайты производителей, либо тонны форумов с сообщениями вида: "а на телефоне X с симкой Y будет работать или нет?". Описания принципов работы таким образом найти не получилось.&lt;br /&gt;&lt;br /&gt;Все дальнейшее - мои предположения по теме, в правильности которых я уверен процентов на 80. Буду рад, если кто-то знающий наверняка подтвердит это или опровергнет.&lt;br /&gt;&lt;br /&gt;Итак, что же из себя представляют волшебные средства для unlock-а телефонов? Это тонкая (~0,7 мм) печатная плата с микросхемкой, подкладываемая под вашу SIM-карту. Чтобы такой "бутерброд" влез в держатель для SIM-карты, приходится подрезать вашу SIM-карту или вырезать в ней дырку (как показано на рисунке справа), в которую войдет микросхема.&lt;br /&gt;&lt;br /&gt;В инструкции по эксплуатации подобный девайсов есть два любопытных момента:&lt;br /&gt;1)Требуется, чтобы ваша сим-карта до этого была хоть раз вставлена в телефон и зарегистрировалась в нужной вам сети. Вынуть сим-карту из упаковки, подложить "анлокер" и включить телефон нельзя - телефон не зарегистрируется в сети.&lt;br /&gt;2)Иногда (как утверждают производители - не слишком часто) после потери сети телефон не будет в ней регистрироваться заново. Тогда надо вынуть симку и анлокер, засунуть симку в другой аппарат, зарегистрироваться в сети, и вернуть симку на место.&lt;br /&gt;&lt;br /&gt;Похоже, тут и есть ключ к разгадке. Берем GSM 11.11 "Specification of the Subscriber Identity Module -&lt;br /&gt;Mobile Equipment (SIM - ME) interface" и читаем (фигурно порезано и откомментировано мной. Сокращение "ME" - это телефон, mobile equipment):&lt;br /&gt;&lt;br /&gt;"11.2.1	SIM initialization&lt;br /&gt;After SIM activation[...], if the CHV1 verification procedure (&lt;strong&gt;&lt;em&gt;т.е. проверка PIN-кода&lt;/em&gt;&lt;/strong&gt;) is performed successfully, the ME then runs the SIM Phase request procedure.&lt;br /&gt;For a SIM requiring PROFILE DOWNLOAD, then the ME shall perform the PROFILE DOWNLOAD procedure in accordance with TS&amp;nbsp;11.14&amp;nbsp;[27]. [...] then the SIM is able to allow the REHABILITATE command to rehabilitate EF&lt;sub&gt;IMSI&lt;/sub&gt; and EF&lt;sub&gt;LOCI&lt;/sub&gt;.&lt;br /&gt;[..]&lt;br /&gt;For a SIM of Phase 2 or greater, GSM operation shall only start if one of the two following conditions is fulfilled:&lt;br /&gt;‑	if EF&lt;sub&gt;IMSI&lt;/sub&gt; and EF&lt;sub&gt;LOCI&lt;/sub&gt; are not invalidated, the GSM operation shall start immediately;&lt;br /&gt;‑	if EF&lt;sub&gt;IMSI&lt;/sub&gt; and EF&lt;sub&gt;LOCI&lt;/sub&gt; are invalidated, the ME rehabilitates these two EFs.&lt;br /&gt;[..]&lt;br /&gt;then GSM operation shall start."&lt;br /&gt;&lt;br /&gt;Тут есть несколько важных для нас моментов: если в телефоне установлена "модная" и современная SIM-карта, то сразу после проверки PIN-кода телефон должен сделать "PROFILE DOWNLOAD" и доложить SIM-карте о своих возможностях (размер экрана, поддержка доп. услуг и т.п.), а SIM-карта, в свою очередь, рассказывает телефону о своих возможностях (в соответствии со стандартом GSM 11.14). В частности, SIM-карта может сказать, что она умеет выдавать нотификации о том, что какая-то важная информация, хранящаяся на SIM-карте, изменилась. Запомним это.&lt;br /&gt;Далее, &lt;strong&gt;EF&lt;sub&gt;IMSI&lt;/sub&gt;&lt;/strong&gt; and &lt;strong&gt;EF&lt;sub&gt;LOCI&lt;/sub&gt;&lt;/strong&gt; - это elementary file-ы (т.е. области памяти) в SIM-карте, хранящие информацию о IMSI и последнем известном location телефона в сети.&lt;br /&gt;&lt;br /&gt;Получается, что анлокер работает примерно таким образом:&lt;br /&gt;Телефон после включения делает запрос PIN-кода, передает его SIM-карте и начинает процедуру "SIM Initialization". Телефон запрашивает содержимое EF&lt;sub&gt;IMSI&lt;/sub&gt;, чтобы проверить, не invalidated ли оно. Как я понимаю, где-то в этот момент в firmware телефона отрабатывают процедуры "залочки", проверяющие, не сунули ли в телефон "левый" SIM. Анлокер, который принимает все запросы от телефона, не передает их оригинальной SIM-карте, а отвечает вместо нее, возвращая телефону "левый" IMSI, принадлежащий нужному оператору - тому, на которого залочен телефон.&lt;br /&gt;&lt;br /&gt;Когда телефон добирается до фазы "Location Information request", анлокер перестает вмешиваться в работу телефона и SIM-карты, и в эфир уходит реальный IMSI, хранящийся на реальной SIM-карте, вставленой за "анлокером".&lt;br /&gt;&lt;br /&gt;Я не уверен, не съедут ли у телефона мозги от того, что с какого-то момента SIM-карта начнет отдавать другой IMSI. Впрочем, в GSM 11.14 есть лазейка (раздел 6.4.7.1, "EF&lt;sub&gt;IMSI&lt;/sub&gt; changing procedure"): SIM-карта с SIM Toolkit может послать телефону уведомление о том, что ее IMSI изменился (например, в результате over-the-air обновления конфигурации SIM-карты со стороны оператора), и телефон должен принять это к сведению, переспросить новое значение IMSI и без перерегистрации в сети работать дальше.&lt;br /&gt;&lt;br /&gt;Возможно, анлокер использует эту функцию для того, чтобы пройти включение телефона и инициализацию SIM-а с одним значением IMSI, а затем поменять его на другое.&lt;br /&gt;&lt;br /&gt;В простых моделях анлокеров есть настройка под названием "IMSI Patch count", которую рекомендуют устанавливать в значение "1" или "2". Подозреваю, это кол-во начальных обращений к EF&lt;sub&gt;IMS&lt;/sub&gt;, перехватываемых анлокером, в ходе которых он отвечает за SIM-карту, подставляя нужное значение IMSI.&lt;br /&gt;&lt;br /&gt;Остается один вопрос - откуда анлокер узнает, какое значение IMSI надо дать телефону, чтобы тот поверил, что в нем стоит "родная" SIM-карта? Некоторые анлокеры используют "универсальные" значения MCC=001, MNC=01, которые по стандартам GSM являются аналогом сегментов 127.0.0.*, 10.0.* и т.п. из адресного пространства TCP/IP и используются в тестовых сетях. По стандарту любой телефон должен без лишних вопросов принять SIM-карту с такими кодами страны и сети. Другие анлокеры требуют один раз вставить в телефон SIM-карту оператора, на которого он залочен, считывают с нее IMSI и используют в будущем. Наконец, есть анлокеры, которые позволяют с помощью программатора задать коды MCC и MNC, которые будут использоваться.&lt;br /&gt;&lt;br /&gt;PS&lt;br /&gt;Кроме того, я обновил предпоследний пост &lt;a href="http://users.livejournal.com/_adept_/95298.html"&gt;про "псевдо-базовые" и их функции&lt;/a&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:95298</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/95298.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=95298"/>
    <title>Обнаружение реальных IMSI и прослушивание переговоров при помощи "виртуальных базовых" - материалы.</title>
    <published>2009-07-24T17:18:32Z</published>
    <updated>2009-08-06T08:09:52Z</updated>
    <category term="gsm"/>
    <content type="html">Некоторе время тому назад у меня был пост про "виртуальные базовые станции" (&lt;a href="http://users.livejournal.com/_adept_/90195.html"&gt;http://users.livejournal.com/_adept_/90195.html&lt;/a&gt;) и их возможности.&lt;br /&gt;&lt;br /&gt;И тут мне ВНЕЗАПНО попались на глаза любопытные материалы по этому поводу&lt;a name="cutid1"&gt;&lt;/a&gt;:&lt;br /&gt;  	&lt;ul&gt;&lt;li&gt;&lt;p&gt;Обзорное описание принципов работы Rohde &amp;amp; 	Schwarz RA 900: 	&lt;a href="http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/seminare/itsss07/imsi_catcher.pdf"&gt;http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/seminare/itsss07/imsi_catcher.pdf&lt;/a&gt;&lt;/p&gt; 	&lt;/li&gt;&lt;li&gt;&lt;p&gt;Материалы судебного разбирательства 	по патентным правам, обсуждающие детали 	реализации подобных устройств: 	&lt;a href="http://www.martinhowe.co.uk/pubs/legal/mmivcellxion_judgment_11march2009.doc"&gt;http://www.martinhowe.co.uk/pubs/legal/mmivcellxion_judgment_11march2009.doc&lt;/a&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;Вторая ссылка - это самое оно. Свежее и жирное. Возможно, оно по закону положено быть открытым, но если это произошло по недосмотру - то тащите и читайте, пока его не закрыли. Там в деталях описано устройство подобныйх девайсов.&lt;br /&gt;&lt;br /&gt;Рад, что я по всем основным пунктам не ошибся :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPD:&lt;/b&gt; Короткое резюме своими словами.&lt;br /&gt;По словам производителя, основное назначение устройства - выяснить IMSI/IME телефона, про который известно только то, что он "где-то рядом". Т.е. мы знаем, что вот в этом загороднем доме сидит "подозреваемый" и у него есть телефон, но какой у него IMEI и что за SIM-карта в него вставлена, мы не в курсе.&lt;br /&gt;&lt;br /&gt;Подогнав "псевдо-базовую", можно с большой вероятностью добиться того, чтобы все телефоны вокруг всделали location update через нашу "псевдо-базовую". В результате мы получим информацию о IMSI и IMEI всех телефонов вокруг. Если получится отсеять все "левые" - то останется IMSI нужного телефона. Теперь можно идти к оператору и ставить его на прослушку при помощи СОРМ.&lt;br /&gt;&lt;br /&gt;Про перехват звонков написано ровно то, что было у меня в после: можно перехватить исходящие звонки, входящие - нельзя. Для перехвата исходящих звонков необходимо дать с "псевдо-базовой" команду на отключение шифрования на трубке подозреваемого. Кроме этого, все прочие товарищи в зоне покрытия псевдо-базовой в этом случае будут сидеть без связи вообще. Т.к. все это легко "спалить", рекомендуется для прослушивания использовать СОРМ и не выделываться.&lt;br /&gt;&lt;br /&gt;Вот, вкратце, и все.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:95162</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/95162.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=95162"/>
    <title>Практика функционального программирования</title>
    <published>2009-07-22T14:26:35Z</published>
    <updated>2009-07-22T15:30:18Z</updated>
    <category term="haskell"/>
    <content type="html">Вышел первый выпуск журнала, посвящённого практике функционального и декларативного программирования, чему я очень рад. В нем есть моя статья, и этому я рад еще больше.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://fprog.ru/2009/issue1/" target="_blank"&gt;http://fprog.ru/2009/issue1/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Организатор процесса - &lt;span class='ljuser ljuser-name_lionet' lj:user='lionet' style='white-space: nowrap;'&gt;&lt;a href='http://lionet.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://lionet.livejournal.com/'&gt;&lt;b&gt;lionet&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;. Авторы статей: &lt;span class='ljuser ljuser-name_thesz' lj:user='thesz' style='white-space: nowrap;'&gt;&lt;a href='http://thesz.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://thesz.livejournal.com/'&gt;&lt;b&gt;thesz&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name__darkus_' lj:user='_darkus_' style='white-space: nowrap;'&gt;&lt;a href='http://users.livejournal.com/_darkus_/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://users.livejournal.com/_darkus_/'&gt;&lt;b&gt;_darkus_&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name_antilamer' lj:user='antilamer' style='white-space: nowrap;'&gt;&lt;a href='http://antilamer.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://antilamer.livejournal.com/'&gt;&lt;b&gt;antilamer&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class='ljuser ljuser-name_kurilka' lj:user='kurilka' style='white-space: nowrap;'&gt;&lt;a href='http://kurilka.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://kurilka.livejournal.com/'&gt;&lt;b&gt;kurilka&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; и &lt;span class='ljuser ljuser-name_alexott' lj:user='alexott' style='white-space: nowrap;'&gt;&lt;a href='http://alexott.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://alexott.livejournal.com/'&gt;&lt;b&gt;alexott&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;Официальный анонс:&lt;br /&gt;&lt;br /&gt;Первый номер журнала посвящён погружению в предмет функционального программирования. Вводные статьи Сергея Зефирова «Лень бояться» и Романа Душкина «Функции и функциональный подход» затрагивают философию парадигм программирования. Более практически направленная часть журнала представлена статьёй Евгения Кирпичёва «Изменяемое состояние: опасности и борьба с ними», классифицирующей типы проблем, возникающих при небрежном использовании сущностей с изменяемым состоянием, и следующей за ней статьёй Дмитрия Астапова «Давно не брал я в руки шашек», на протяжении нескольких страниц раскрывающей подход проектирования «сверху вниз» на подробном примере написания игры в шашки на языке Haskell. Статья Дэна Пипони «Моноиды в Haskell и их использование» в переводе Кирилла Заборского простым языком обьясняет практическое применение моноидов для создания элегантных полиморфных алгоритмов. Номер завершается внушительным «Обзором литературы о функциональном программировании» Алексея Отта, содержащим множество ссылок на русскоязычную и англоязычную литературу по разным языкам и аспектам декларативного программирования.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:_adept_:94839</id>
    <link rel="alternate" type="text/html" href="http://users.livejournal.com/_adept_/94839.html"/>
    <link rel="self" type="text/xml" href="http://users.livejournal.com/_adept_/data/atom/?itemid=94839"/>
    <title>ICFPC-2009: Таких не берут в космонавты!</title>
    <published>2009-06-29T23:00:16Z</published>
    <updated>2009-06-29T23:22:09Z</updated>
    <category term="icfpc"/>
    <content type="html">&lt;strong&gt;Имя команды&lt;/strong&gt;: li-monad (спасибо aleksey/jabber.ru за идею)&lt;br /&gt;&lt;strong&gt;Состав&lt;/strong&gt;: я, endless-world, &lt;span class='ljuser ljuser-name_iakovz' lj:user='iakovz' style='white-space: nowrap;'&gt;&lt;a href='http://iakovz.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://iakovz.livejournal.com/'&gt;&lt;b&gt;iakovz&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, при участии blancus.&lt;br /&gt;&lt;strong&gt;Итоговый бал&lt;/strong&gt;: &lt;span class="score"&gt;2234.7171  (12 problems solved)&lt;/span&gt;  &lt;br /&gt;&lt;br /&gt;Поскольку scoreboard традиционно перестал обновляться за пару часов до окончания соревнования, мне сложно сказать, какое же место мы заняли в конце-концов. Если все остальные участники расслаблялись перед финальным свистком и ничего не делали, то это будет 59-е место.&amp;nbsp; Но скорее всего в расстановке сил перед самым финишем наверняка произошли существенные изменения, и я буду рад, если нас не "выдавят" хотя бы из первой сотни.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Как я уже писал, в этом году я перепутал июнь с июлем, и чуть было не пропустил ICFPC вообще. О том, чтобы собирать команду, не могло быть и речи - на это просто не было ни календарного, ни свободного времени. В результате, в последние два дня перед соревнованием я попытался найти команду, к которой можно было присоединиться, но все места уже были заняты.&lt;br /&gt;&lt;br /&gt;В ходе моих поисков на #icfp-contest в последний день, буквально за 6 часов до начала, меня законтачили два человека и предложили объединится в импровизированную команду. Я согласился, тем более, что вероятно было участие еще пары англоязычных персонажей из haskell community. Забегая наперед, с сожалением констатирую, что из этой попытки ничего особо хорошего не вышло, т.к. командного взаимодействия у нас не получилось, и команда буквально развалилась на ходу еще до конца первых суток. Строить общие планы мои соратники по команде не спешили, чем планируют занимаются - не говорили, а в середине второго дня &lt;span class='ljuser ljuser-name_iakovz' lj:user='iakovz' style='white-space: nowrap;'&gt;&lt;a href='http://iakovz.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://iakovz.livejournal.com/'&gt;&lt;b&gt;iakovz&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; вообще пропал, оставив вместо себя полезную ссылку на книгу "Orbital Mechanicas" и приведенного в командную конференцию математика blancus, который честно пытался нам помочь :)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Впочем, обо всем по порядку.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Начатая в прошлом году космическая тема успешно была продолжена и в этом. Если в прошлом году надо было рулить марсоходом, то в этом году нужно было пилотировать спутник.&lt;br /&gt;&lt;br /&gt;Задача сводилась к написанию кода, который выдает "программу" управления спутником для решения задачи по орбитальному пилотированию. Участникам было предложено решить несколько задач с возрастающей степенью сложности, каждую из которых нужно было решить для четырех разных наборов входных данных:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Перевести спутник, движущийся по круговой орбите вокруг центрального тела (Земли), на круговую орбиту с другим радиусом&lt;/li&gt;&lt;li&gt;Произвести "стыковку" с другим спутником, движущимся по круговой орбите&lt;/li&gt;&lt;li&gt;Произвести "стыковку", но при условии, что начальная орбита управляемого спутника и спутника-цели - это не круги, а эллипсы&lt;/li&gt;&lt;li&gt;Пролететь в радиусе 1 км от 11 спутников, движущихся по произвольным орбитам, дозаправляясь топливом на орбитальной заправочной станции и учитывая влияние не только Земли, но и Луны&lt;/li&gt;&lt;/ol&gt;Программа управления спутником состояла из команд по включению двигателя в определенные моменты времени, которое приводила к мгновенному изменению скорости спутника. Эту программу можно было рассчитывать на листике в клеточку, считать в специализированном ПО вроде MATLAB или Mathematica, или генерировать програмным путем. Для проверки корректности рассчетом можно было скормить свою программу в предоставленный организаторами симулятор движения небесных тел и убедиться, что спутник действительно прилетает куда надо.&lt;br /&gt;&lt;br /&gt;Правда, чтобы обеспечить возможность запуска своего кода в любой среде, организаторы скомпилировали свою программу в код некой виртуальной машины, спецификации на которую прилагались в задании. Соответственно, у участников было два пути проверки правильности своих решений - или заливать их на сайт организаторов, где они проходили проверку в течении 5-60 минут, или самостоятельно реализовать описанную виртуальную машину и получить возможность запускать "проверялку" у себя на компьютере.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;День первый, старт соревнования в 21:00 EEST 26.06&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Мы в течении получаса читали задание, а потом собрались в jabber, чтобы его обсудить. Выяснилось, что понимаем мы его примерно одинаково. После этого мы подключились к gobby и совместно набросали высокоуровневый дизайн решения. Где-то в 23:00 все, кроме меня, отвалились спать, не оставив никаких вещественных результатов. Endless-world сказал, что он пишет VM, и завершит ее завтра с утра. Я написал декодирование байт-кода от организаторов в вид, пригодный для потребления виртуальной машиной и набросал код, который объединяет еще не написанные модули - декодер байт-кодов, VM, поиск решений предложенных задач, формирователь файла с решениями и т.п. - и тоже отправился спать&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;День второй, 27.06&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Организаторы приложили к условию задачи ссылку на страницу на wikipedia с описанием одного из &lt;a href="http://en.wikipedia.org/wiki/Hohmann_transfer_orbit"&gt;способов решения первой задачи&lt;/a&gt;. Казалось бы - бери, кодируй и запускай. Однако, быстро решить первую задачу не получилось. Хотя первая версия VM была готова еще в 10:00, нормальной запустить ее удалось только в 13:40. Мешали как баги, допущенные нами в реализации, так и баги, допущенные организаторами в спецификации. Кроме того, в библиотеке, которую я использовал для побитового декодирования данных, обнаружился мерзкий баг, который периодически приводил к потере данных. Как известно, эффект от независимых багов не складывается, а умножается, что и привело к такой потере темпа.&lt;br /&gt;&lt;br /&gt;Еще час был потерян из-за того, что все константы, кроме одной, были указаны в условии в шестнадцатеричном виде. Мы этого при беглом чтении не заметили, и указывали номер задачи в виде 0x1001 вместо 1001.&amp;nbsp; К 15:00 мы с endless-world независимо друг от друга реализовали две версии решателя, вычисляющего параметры Гомановского перехода на другую круговую орбиту, и выяснили, что мы совсем забыли с институтских времен и физику, и математику, и тригонометрию. Разнообразные досадные ошибки (забыли домножить в нужном месте на массу Земли; забыли, как рассчитать вектор, перпендикулярный к данному; ...) привели к тому, что в 17:00 спутник у нас уже летал, но в цель попасть никак не мог.&lt;br /&gt;&lt;br /&gt;Перепробовав несколько вариантов расчета перпендикуляра, "смотрящего" в нужную нам сторону (да-да, и нечего смеяться), пересчитав несколько раз формулы из wikipedia по найденной умной книге и оптимизировав VM, чтобы она не отжирала память при работе, мы в конце-концов получили в 19:00 код, решающий первую задачу, для всех четырех вариантов известных старторвых условий.&lt;br /&gt;&lt;br /&gt;Ура! Получается, что мы еще успеваем сдать какие-то результаты для участия в т.н. lightning round - соревновании по результатам, полученным в течении первых суток. Но не тут-то было - отосланные организаторам программы управления были проверены и получили оценку "CRASHED!"&lt;br /&gt;&lt;br /&gt;Возможных причин было несколько: неправильный формат файла с результатами, спутник врезался в Землю или спутник истратил в ходе маневров все топливо. Т.к. я был уверен, что летаем мы правильно и топливо экономим, я принялся сличать генерируемый нами файл с описанием формата в спецификации. Вроде бы все делаем правильно, а результат не засчитывают - ну, хоть убейся. В конце-концов я смирился с тем, что в формате файла ошибок у нас нет. Получается, мы плохо управляем спутником? &lt;br /&gt;&lt;br /&gt;Как выяснилось - мы плохо прочитали и поняли условие задачи. Нам казалось, что если в программе записано "в момент времени T подать имульс V в направлении a", то двигатели включатся и выключатся. А по спецификации получалось, что они включатся и будут работать до тех пор, пока в программе не встретится команда "в момент времени T' подать импульс величиной 0". Соответственно, по мнению организаторов все наши программы врубали газ на полную и летели, куда глаза глядят, вплоть до исчерпания запасов топлива.&lt;br /&gt;&lt;br /&gt;К сожалению, осознание этого факта пришло ко мне уже после окончания lightning round-а. Первые наши результаты были приняты уже 28-го числа, сразу после полуночи. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;День третий, 28.06&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Выяснилось, что организаторы ошиблись в своем коде, и для первой задачи можно получить больше баллов не экономя топливо, а наоборот - тратя его :) Организаторы сказали, что так уже и будет - для первой задачи больше балов получают "растратчики", а для всех следующих - те, кто экономит топливо.&lt;br /&gt;&lt;br /&gt;Endless-world прочел об этом в блоге организаторов и реализовал хак, который сжигает остатки топлива после выхода на целевую орбиту, и мы получили за первую задачу 382 балла из 400 возможных!&lt;br /&gt;&lt;br /&gt;Вторая задача похожа на первую - ведь это, по сути, тот же переход на другую орбиту, который мы уже умеем делать. Правда, после перехода на нужную орбиту надо чуть разогнаться (или затормозить), чтобы орбита из круговой стала эллиптической и мы догнали таким образом спутник, с которым нам надо состыковаться. Впрочем, перейдя к решению второй задачи, я обнаружил, что мы по-прежнему где-то ошибаемся в рассчете перпендикуляров к радиусу орбиты - в двух случаях из четырех во второй задаче наш спутник тормозит вместо разгона и врезается в Землю :(&lt;br /&gt;&lt;br /&gt;Кроме этого, в коде решателя первой задачи (который я хотел переиспользовать для решения второй задачи) нашлись два бага, которые компенсировали друг друга. Со скрипом и проблемами, с многочисленными правками физических рассчетов, к 16:00 появилась версия решения, которая пыталась выполнить phasign -- тот самый маневр по догонянию спутника-цели. &lt;br /&gt;&lt;br /&gt;Задание считалось решенным, если наш спутник находился в радиусе километра от цели в течении 900 секунд и при этом не пользовался двигателями. Наше решени замечательно разгонялось, но тормозить у него получалось из рук вон плохо - наш спутник не мог вернуться обратно на круговую орбиту, и быстро удалялся от цели.&lt;br /&gt;&lt;br /&gt;Попытки сделать какой-то "подруливатель" успехом не увенчались - становилось только хуже. Во второй половине дня я плюнул, взял Mathematica и самостоятельно вывел решение задачи phasing-а с нуля. Результат получился выше всяких похвал - маневр завершался в пределах +-50 метров от цели, и в течении 900 секунд мы отлетали максимум метров на 100-200. Вторая задача пошла в зачет :)&lt;br /&gt;&lt;br /&gt;Мы не писали какого-то отдельного специального визуализатора - наша VM выводила отладочный лог с координатами нашего и целевого спутников на каждом шаге, а я использовал gnuplot для рисования красивых по этому логу:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://adept.homeunix.net/icfpc2009/images/2002/orbit.png" alt="" style="float: none;" width="600" /&gt;&lt;br /&gt;На первом графике нарисованы орбиты. Видно, как наш спутник стартует почти из центра целевой (зеленой) орбиты, выходит на нее по витку эллипса и сразу переходит на эллиптическую орбиту для того, чтобы догнать цель. В момент выхода на целевую орбиту цель находится "за" нами (по направлению вращения), поэтому наш спутник переходит на орбиту большей длины, рассчитанную так, чтобы по завершению одного оборота мы и цель оказались в одной точке. В этот момент выполняется коррекция курса и наш спутник возвращается на целевую (зеленую) орбиту в 50 метрах от цели.&lt;br /&gt;&lt;img src="http://adept.homeunix.net/icfpc2009/images/2002/distance.png" alt="" style="float: none;" width="600" /&gt;&lt;br /&gt;На втором графике видно, как менялось расстояние до цели (синяя кривая) и расстояние от нашего спутника до Земли (красная кривая) с течением времени. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;День третий, 29.06&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;В общем чат-логе за этот день нет ни одной строчки - все куда-то окончательно разбежались :(&lt;br /&gt;&lt;br /&gt;Я долго и безуспешно пытался повторить вчерашний успех и обобщить решатель второй задачи на случай произвольных эллиптических кривых. Получалось у меня плохо, точнее сказать - совсем не получалось. Кроме того, параметры нашей и целевой орбиты надо было еще рассчитать, зная только координаты спутников в тот или иной момент времени. &lt;br /&gt;&lt;br /&gt;К сожалению, все доступные мне источники знаний, как сговорившись, рассказывали о том, как рассчитать параметры орбиты по двум наблюдениям летящего тела - т.е. нам известны только два расстояния от летящего тела до земли и угол между векторами наблюдения. Это так называемая задача Ламберта. Она не может быть решена в общем виде аналитически, требуется составлять и решать численными методами дифференциальные уравнения. Я потратил пол-дня, пытаясь реализовать искомое, но безуспешно. К середине дня мною был найден в сети документ, описывающий значительно более простой метод Гиббса, позволяющий вычислить в аналитическом виде параметры орбиты по трем наблюдениям.&lt;br /&gt;&lt;br /&gt;К сожалению, универсальный решатель, рассчитывающий переход с одной эллиптической орбиты на другую, у меня так и не получилось рассчитать и написать. В конце-концов я вручную, методом проб и ошибок, подобрал параметры к имеющимся у меня на тот момент уравнениям, и решил четыре сценария третьей задачи - увы, кое-как, далеко не оптимально. Это и был мой финальный результат. &lt;br /&gt;&lt;br /&gt;Невзирая на все ошибки со стороны организаторов (было выпущено 8 уточняющих версий спецификации), мне соревнование этого года понравилось больше, чем прошлого. Остается надеятся, что когда-нибудь кто-нибудь из организаторов повторит &lt;a href="http://users.livejournal.com/_adept_/24049.html"&gt;успех 2006-го года&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Отдельно хотелось бы поблагодарить любимую &lt;span class='ljuser ljuser-name_yulanta' lj:user='yulanta' style='white-space: nowrap;'&gt;&lt;a href='http://yulanta.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://yulanta.livejournal.com/'&gt;&lt;b&gt;yulanta&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; за предоставленную возможность предаваться сомнительным развлечениям :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.icfpcontest.org/scoreboard.php"&gt;Официальный scoreboard, по состоянию за 5 часов до окончания соревнования&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;И, наконец, немного статистики и всяких фактов&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;Объем кода: &lt;strong&gt;1077&lt;/strong&gt; строк (из них 100 - VM, и 100 - базовые функции для физических рассчетов), язык - Haskell&lt;br /&gt;Скорость работы VM: ~&lt;strong&gt;10 секунд&lt;/strong&gt; на любой сценарий задачи 1&lt;br /&gt;Кол-во commit-ов в репозиторий: &lt;strong&gt;170&lt;/strong&gt; (151 - я, 14 - endless-world, 5 - &lt;span class='ljuser ljuser-name_iakovz' lj:user='iakovz' style='white-space: nowrap;'&gt;&lt;a href='http://iakovz.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://iakovz.livejournal.com/'&gt;&lt;b&gt;iakovz&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;)&lt;br /&gt;Кол-во найденных в сети и просмотренных книг по орбитальной механике: &lt;strong&gt;15&lt;/strong&gt;&lt;br /&gt;Из них полезных: &lt;strong&gt;3&lt;/strong&gt;&lt;br /&gt;Кол-во памяти, потребляемой первой версией VM: &lt;strong&gt;от 400 до 3000 Мб&lt;/strong&gt;, в зависимости от сценария (из-за неудачного design decision сборщик мусора не мог собрать старые версии состояния VM)&lt;br /&gt;Кол-во памяти, потребляемой VM после оптимизации: &lt;strong&gt;от 5 до 20 мб&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;Финальная версия кода&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;&lt;a href="http://adept.homeunix.net/icfpc2009"&gt;http://adept.homeunix.net/icfpc2009&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;Отчеты и репозитории других команд (список будет пополняться)&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://87.251.141.10/icfpc/svn/trunk"&gt;http://87.251.141.10/icfpc/svn/trunk&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://bitbucket.org/xa4a/icfpc09/src"&gt;http://bitbucket.org/xa4a/icfpc09/src&lt;/a&gt; , &lt;a href="http://img230.imageshack.us/img230/7020/screenshot3p.png"&gt;http://img230.imageshack.us/img230/7020/screenshot3p.png&lt;/a&gt; , &lt;a href="http://funkyimg.com/u2/921/187/screenshot-2009-06-29--21-14-17.png"&gt;http://funkyimg.com/u2/921/187/screenshot-2009-06-29--21-14-17.png&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
</feed>
