Здравствуйте, Правдоруб, Вы писали:
aqt>>Особенно понравились выделенные фрагменты, которые Вы советуете взять на вооружение. Так держать! П>Заголовок там звучит как
А то, что бывают разные кодировки Вы слышали?!
Здравствуйте, machine3000, Вы писали:
M>Если не в лом, гляньте на сколько бачей примерно автор кода у вас бы потянул.
Ради интереса переписал на немерле
Забирает данные из stdin, отдает в stdout, дебужную информацию и ошибки пишет в stderr
using System;
using System.IO;
using System.Collections.Generic;
using SCG = System.Collections.Generic;
using Nemerle.Collections;
using Nemerle.Utility;
using Nemerle.Text;
public class Converter
{
[Record]
class Unit
{
public Name : string;
public Weight : double;
public Cluster : Cluster;
public override ToString() : string
{
$"Unit($Name, $Weight)";
}
}
class Cluster
{
private _units : Hashtable.[Unit, byte] = Hashtable.[Unit, byte]();
public Units : SCG.ICollection.[Unit]
{
get { _units.Keys; }
}
public Add(unit : Unit) : void
{
_units.Add(unit, 0);
}
}
public Add(weight : double, name : string, weightTo : double, nameTo : string) : void
{
WriteLine($"$((weight, name, weightTo, nameTo))");
def doubleEq(d1 : double, d2 : double)
{
def d = d1 - d2;
if (d < 0)
d >= -double.Epsilon;
else
d <= double.Epsilon;
}
def addUnit(name, cluster, weight)
{
def unit = Unit(name, weight, cluster);
_unitNameToUnit[name] = unit;
cluster.Add(unit);
}
def mergeClusters(cluster1, cluster2, weight : double)
{
def merge(cluster1, cluster2, weight)
{
foreach (unit2 in cluster2.Units)
addUnit(unit2.Name, cluster1, unit2.Weight * weight);
}
// Заливаем единици из меньшего кластера в больший.
// Таким образом алгоритм получается O(N*log(N)) в худшем случае.if (cluster1.Units.Count > cluster2.Units.Count)
merge(cluster1, cluster2, weight);
else
merge(cluster2, cluster1, 1 / weight);
}
def weight = weightTo / weight;
match (_unitNameToUnit.Get(name), _unitNameToUnit.Get(nameTo))
{
| (Some(unit), Some(unitTo)) => // Известны обе единици измерения
WriteLine($"($unit, $unitTo)");
if (InSameCluster(unit, unitTo))
{
// Если в одном кластере проверяем не протеворечит ли новое значение тому что уже есть.
when (!doubleEq(weight, unitTo.Weight / unit.Weight))
throw Exception("Invalid data.");
}
else
{
// Если в разных кластерах сливаем кластеры
mergeClusters(unit.Cluster, unitTo.Cluster, weight * unit.Weight / unitTo.Weight);
}
| (Some(unit), None) => // Известна одна из единиц измерения. Создаем вторую и помещаем ее в кластер первой.
WriteLine($"($unit, None)");
addUnit(nameTo, unit.Cluster, unit.Weight * weight);
| (None, Some(unitTo)) =>
WriteLine($"(None, $unitTo)");
addUnit(name, unitTo.Cluster, unitTo.Weight / weight);
| (None, None) => // Не известны обе единици измерения.
WriteLine("(None, None)");
def cluster = Cluster();
addUnit(name, cluster, 1.0);
addUnit(nameTo, cluster, weight);
}
def clusters()
{
def clusters = Hashtable();
foreach (unit in _unitNameToUnit.Values)
clusters[unit.Cluster] = 0;
clusters.Keys;
}
foreach (cluster in clusters())
WriteLine($"..$(cluster.Units)");
WriteLine("");
}
public getConversionWeight(name : string, nameTo : string) : option[double]
{
match (_unitNameToUnit.Get(name), _unitNameToUnit.Get(nameTo))
{
| (Some(unit), Some(unitTo)) when InSameCluster(unit, unitTo) =>
Some(unitTo.Weight / unit.Weight)
| _ =>
None()
}
}
public convert(value : double, name : string, nameTo : string) : double
{
match (getConversionWeight(name, nameTo))
{
| Some(weight) => value * weight;
| _ => throw Exception("Invaluid conversion.");
}
}
static InSameCluster(u1 : Unit, u2 : Unit) : bool
{
u1.Cluster : object == u2.Cluster : object;
}
static WriteLine(line : string) : void
{
Console.Error.WriteLine(line);
}
_unitNameToUnit : Hashtable.[string, Unit] = Hashtable.[string, Unit]();
}
public module UnitConvertor
{
public ReadAllLinesLazy(this text : TextReader) : SCG.IEnumerable.[string]
{
def loop(line)
{
| null =>
()
| line =>
yield line;
loop(text.ReadLine())
}
loop(text.ReadLine())
}
public Main() : int
{
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo("");
def process(input : TextReader, output : TextWriter)
{
def converter = Converter();
def processLine(line)
{
def writeResult(w1, n1, w2, n2)
{
output.WriteLine($"$w1 $n1 = $w2 $n2");
}
regexp match (line)
{
// Ищем строку вида "1 day = 24.0 hour"
| @"\s*(?<w1>\S+)\s+(?<n1>\S+)\s*=\s*(?<w2>\S+)\s+(?<n2>\S+)\s*" =>
match (w1, n1, w2, n2)
{
| (w1, n1, "?", n2) =>
def w1 = double.Parse(w1);
def w2 = converter.convert(w1, n1, n2);
writeResult(w1, n1, w2, n2);
| ("?", n1, w2, n2) =>
def w2 = double.Parse(w2);
def w1 = converter.convert(w2, n2, n1);
writeResult(w1, n1, w2, n2);
| (w1, n1, w2, n2) =>
converter.Add(double.Parse(w1), n1, double.Parse(w2), n2);
}
// Пропускаем пустые строки
| @"\s*" => ();
// Ругаемся на строки не подходящие под шаблон
| _ => throw Exception("Invalid input.");
}
}
mutable lineNumber = 0;
foreach (line in input.ReadAllLinesLazy())
{
try
{
++lineNumber;
processLine(line);
}
catch
{
| ex is Exception =>
throw Exception($"Error ta line $lineNumber", ex);
}
}
}
try
{
process(Console.In, Console.Out);
0;
}
catch
{
| ex is Exception =>
Console.Error.WriteLine(ex);
-1;
}
}
}
stdin
1 day = 24.0 hour
60 minute = 1 hour
10.0 glob = 1 decaglob
1000 msecond = 1 second
1.0 gigaglob = 1000 megaglob
1.0 kiloglob = 1000 glob
1000 kiloglob = 1 megaglob
1 minute = 60 second
1 hour = 3600 second
2 hour = ? second
? hour = 86400 second
1 day = ? second
000.001 day = ? msecond
20.0 glob = ? decaglob
? gigaglob = 100000000000 decaglob
stdout
2 hour = 7200 second
24 hour = 86400 second
1 day = 86400 second
0.001 day = 86400 msecond
20 glob = 2 decaglob
1000 gigaglob = 100000000000 decaglob
Здравствуйте, WolfHound, Вы писали:
M>>Если не в лом, гляньте на сколько бачей примерно автор кода у вас бы потянул. WH>Ради интереса переписал на немерле
Что-то у меня на ночь глядя замкнуло. В классе Cluster Hashtable не нужен. Достаточно List.
class Cluster
{
private _units : List.[Unit] = List.[Unit]();
public Units : SCG.ICollection.[Unit]
{
get { _units; }
}
public Add(unit : Unit) : void
{
_units.Add(unit);
}
}
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, kikap, Вы писали:
N>>1. Software process (хоть какой) присутствует? K>Процесс очень простой — ad hoc. И другого пока применить невозможно. Но качество результирующего кода таково что я давно такого не видел. Если вы владеете вопросом и сможете внедрить какой-то процесс, который поможет разработке — you're very welcome.
N>>2. Сколько минимум часов в неделю?
K>40. Мы скорее уволим человека, который не справляется с работой, чем будем заставлять его перерабатывать. Это просто не окупается. С другой стороны есть люди, которые работают взахлеб по 100 часов в неделю, а потом неделю бездельничают.
100 часов? В неделю?
Что касается 40 часов, то ваша цель — это 40 часов работы или выполнение плана?
Здравствуйте, machine3000, Вы писали:
M>только не 7 штук, а, скажем, 2^24-1, то, по-моему, "mergeClusters" тут будет умножать и умножать... Не линейная сложность короче.
Сложность у алгоритма O(N*log(N)) в худшем случае. И я об этом написал.
Доводить ее до линейной в данном случае не имеет смысла ибо 2^24-1 единиц измерения да чтобы еще и измеряли одно и тоже... такого не бывает впринципе.
За то мое решение было написано за вечер в перерывах между чтением RSDN, его легко понять и легко расширять (обрати внимание насколько легко я добавил возможность ? быть не только справа от = но и слева). Да на С++ получилось бы несколько (всетки немерле болие мощьный язык) хуже но не сильно.
Так что не нужно переусложнять задачу.
И вобще задачи нужно решать самым простым способом которым можно получить приемлемое решение.
Кстати что-то мне подсказывает что мое решение легко поймут даже те кто немерле не знает. А вот разобраться в твоем...
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, machine3000, Вы писали:
M>Да, похоже умение придумывать линейные алгоритмы на хрен никому не упало. Вот так вот — век живи, век учись. Знал бы прикуп, жил бы ... в Зеленограде.
Не правильный вывод.
Оно не нужно там где не нужны линейные алгоритмы ценой усложнения решений.
Те если (как в данном случае) с линейным алгоритмом возьни сильно больше чем с O(N*log(N)), а толку 0 то в топку линейный алгоритм.
Кстати первая версия вобще была O(N^2). Но тк преобразование в O(N*log(N)) стоило лишь незначительного усложнения mergeClusters я это сделал.
Если бы это было сложнее то я скорей всего бы забил ибо предпологаемый (в реальной жизни я бы уточнил) сценарий использования такой что
1)Единиц измерения очень мало.
2)Вопросов на которые нужно ответить очень много.
Те скорость инициализации особого значения не имеет, а ответ на вопрос имеет у меня сложность O(1).
Короче хороший программист это не тот кто только и умеет что придумывать линейные решения, а тот кто может быстро оценить несколько решений и выбрать лучшее соотношение цена/качество.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Короче хороший программист это не тот кто только и умеет что придумывать линейные решения, а тот кто может быстро оценить несколько решений и выбрать лучшее соотношение цена/качество.
"цена/качество" можно оценить только в каком-то глобальном контексте. Например, если знать, что конвертировать будут валюты, то и говорить не о чем. А если речь идёт о тестовом задании, то его цель, очевидно, выяснить возможности кандидата. И мне казалось, что демонстрация возможностей в данном случае не возбраняется. Тем более, что так задача выглядит подозрительно простой для такой вакансии.
Здравствуйте, machine3000, Вы писали:
M>"цена/качество" можно оценить только в каком-то глобальном контексте. Например, если знать, что конвертировать будут валюты, то и говорить не о чем. А если речь идёт о тестовом задании, то его цель, очевидно, выяснить возможности кандидата. И мне казалось, что демонстрация возможностей в данном случае не возбраняется. Тем более, что так задача выглядит подозрительно простой для такой вакансии.
Вот они и выяснили что ты на ровном месте усложняешь решение...
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Объявление в общем и целом остается в силе, единственное что теперь нам нужен скорее алгоритмический человек, с неплохим запасом скажем в области теории графов и комбинаторики. Если Вы представляете себе как работает в юниксе gated и в принципе способны его написать (идеально — полностью автономно, но годится и под чутким руководством), то Вы похожи на человека, который нам нужен
Отладочный лог прошлой процедуры найма людей на работу можно почитать тут: http://kika.livejournal.com/tag/joboffer
там есть немного обценной лексики, но беззлобно
Люди без московской прописки, женщины, геи, лесбиянки, негры, удаленщики, курящие, пьющие и проч — welcome, we are equal opportunity employer. Главное чтобы Вы были вменяемы, способны к самостоятельной работе, умели задавать нормальные вопросы и задавать каждый вопрос только один раз. Ну и не боялись делать что-то что Вы раньше не делали.
Здравствуйте, kikap, Вы писали:
K>Объявление в общем и целом остается в силе, единственное что теперь нам нужен скорее алгоритмический человек, с неплохим запасом скажем в области теории графов и комбинаторики. Если Вы представляете себе как работает в юниксе gated и в принципе способны его написать (идеально — полностью автономно, но годится и под чутким руководством), то Вы похожи на человека, который нам нужен
K>>Если Вы представляете себе как работает в юниксе gated и в принципе способны его написать (идеально — полностью автономно, но годится и под чутким руководством), то Вы похожи на человека, который нам нужен
M>А что это за фигня такая — gated?
Не заморачивайся, люди, не умеющие пользоваться google ему не подойдут, я думаю
Здравствуйте, kikap, Вы писали:
K>Люди без московской прописки, женщины, геи, лесбиянки, негры, удаленщики, курящие, пьющие и проч — welcome, we are equal opportunity employer.
Здравствуйте, BulatZiganshin, Вы писали: K>>Люди без московской прописки, женщины, геи, лесбиянки, негры, удаленщики, курящие, пьющие и проч — welcome, we are equal opportunity employer. BZ>а если всё это одновременно?
И гей и лесбиянка? Ну по крайней мере на собеседование надо пригласить, посмотреть.
Здравствуйте, kikap, Вы писали:
K>Здравствуйте, BulatZiganshin, Вы писали: K>>>Люди без московской прописки, женщины, геи, лесбиянки, негры, удаленщики, курящие, пьющие и проч — welcome, we are equal opportunity employer. BZ>>а если всё это одновременно?
K>И гей и лесбиянка? Ну по крайней мере на собеседование надо пригласить, посмотреть.
праивльный ответ был бы "гей без московской прописки? прописку дадим, дадим..."
Здравствуйте, kikap, Вы писали:
K>Здравствуйте, nerpabc, Вы писали:
N>>1. Software process (хоть какой) присутствует? K>Процесс очень простой — ad hoc. И другого пока применить невозможно.
Вам никогда не приходило, что разумнее сначала нанимать аналитика для написание спек и архитектора для проектирования архитектуры, а уже потом искать программеров, которые станут это реализовывать?
Знаете как это выглядит? Вы приводите на стройплощадку прораба c инженером и говорите "нужно построить 20-этажный дом с магазином на первом этаже. Чертежей пока нет, как сделаете первый этаж, может, нарисуем". Что они вам скажут?