В теории LINQ позволяет записать любой алгоритм в 1 строку. Вот только в случае простых чисел и прочих элементарных и часто вызываемых алгоритмов - лучше всё равно расписывать по старинке, потому что иначе будет огромная потеря производительности.
Ну, на всяк - приведите тот код в 1 строчку и алгоритм решета Эратосфена на старом паскале.
При переводе на новый всегда есть что улучшить, хотя бы те же for var и элементарные оптимизации для .Net, что увижу из такого - скажу.
Но это кстати спорно. Вообще программа будет хотя бы 3 строчки, потому что ещё begin и end., поэтому я сказал алгоритм.
А ещё можно ли это считать 1 строчкой?))
begin
Arr(0).ForEach(_o->begin %любой алгоритм% end);
end.
По моему это уродливое форматирование, поэтому однострочной программой лучше считать ту - в которой всего 1 end. Не begin, потому что case-end и т.п. в 1 строчку - тоже кривое форматирование.
Однако я уже не помню что за алгоритм, потому что это было давно, но однажды от нечего делать я решил записать какой то сложный алгоритм однострочным, основываясь на этом же определении (1 end на программу).
И, в общем, после пары часов говнокоденья я закончил логически доказав что всех функций Linq и PABCSystem не хватает и это невозможно написать без введения дополнительной переменной. То есть написать можно только в 2 строчки.
А вообще вроде вспомнил. Не тот самый алгоритм но смысл.
Вот пример не решаемой задачи:
Найдите сумму минимума и максимума массива
Как создавать массив - не важно. С клавиатуры/рандомом. Смысл в том что не сохраняя этот массив в переменную - вычислить и минимум и максимум сразу не выйдет.
P.S. Ну и чо уж мне, вот сразу и решение не решаемого:
Осторожно, может вызывать выпадение глаз
begin
Arr&<sequence of integer>(
ArrRandomInteger(30).Println
).Cycle
.Zip(Arr(
Func&<sequence of integer, integer>(s->s.Min),
Func&<sequence of integer, integer>(s->s.Max)
), (s,f)->f(s))
.Sum.Println;
end.
И даже почти работает, эх, если бы ещё не падало)))
begin
Range(2,1000).Where(x -> Range(2,Round(sqrt(x))).All(i->x mod i <> 0)).Print;
end.
Решето Эратосфена
const N = 100;
var
i, k : integer;
A : array[2…N] of boolean;
begin
for i:= 2 to N do
A[i]:= True;
k:= 2;
while kk <= N do begin
if A[k] then begin
i:= kk;
while i <= N do begin
A[i]:= False;
i:= i + k
end;
end;
k:= k + 1
end;
for i:= 2 to N do
if A[i]= True then
writeln(i);
end.
Известный еще по языку С “синдром одной строки” явление нехорошее. В программе должно быть ровно столько строк, сколько требуется, а погоня за упаковкой в строку любого алгоритма - она сущеглупое действо.
Ну уже хотя бы через SeqWhile, а то sqrt, ещё и Round…
Код надо выделять так:
```
код
```
При чём на строчках с ``` - больше ничего быть не должно, а то они ломаются.
Отредактируйте ваше сообщение чтоб нормально выглядело.
По алгоритму - у вас по крайней мере не хватает 1 break-а, нету самой проверки на mod и лишние
Ну, если я понял правильно смысл:
function ВсеПростыеДо(n: integer): sequence of integer;
begin
var res := new boolean[n-1]; // True если не простое
for var i := 2 to n do
begin
var k := 2;
while k*k<i do
begin
if not res[k-2] and (i mod k = 0) then
begin
res[i-2] := true;
break;
end;
k += 1;
end;
if not res[i-2] then yield i;
end;
end;
begin
ВсеПростыеДо(ReadInteger).PrintLines;
end.
В принципе - можно использовать HashSet чтоб сократить использование памяти. То есть хранить только простые числа, и использовать .Contains . Простые числа достаточно хаотично располагаются, поэтому сложность .Contains будет близка к O(1).
Для n = 100 млн оно работало 3.3 с, а предложенное @Sun_Serega - 289 c, т. е. уже в 87 раз дольше.
begin
var n := 100000000;
Milliseconds;
var p := ArrFill(n + 1, True);
(p[0], p[1]) := (False, False);
for var i := 2 to Trunc(Sqrt(n)) do
if p[i] then
begin
var j := i * i;
while j <= n do
begin
p[j] := False;
j += i
end
end;
// for var i := 2 to p.High do;
// if p[i] then
// Print(i)
MillisecondsDelta.Println;
p.Where(t-> t).Count.Println;
end.
А вообще, теперь когда я над этим подумал (в очередной раз переписывая значительную часть OpenCLABC) - для lock такой синтаксис будет ещё полезнее:
begin
var lst := new List<byte>;
var d := new Dictionary<word,real>;
...
var a := lock lst do lst.ToArray;
var d := lock d do d[0];
end.
Через дополнительную переменную выглядит не красиво и объёмно. А ещё тип переменной не авто-выводится, то есть ещё и больно:
begin
var lst := new List<byte>;
var d := new Dictionary<word,real>;
...
var a: array of byte;
lock lst do a := lst.ToArray;
var val: real;
lock d do val := d[0];
end.
Это идиома тернарного оператора. Она изящнее и лучше смотрится для начинающих, чем чужеродный для Паскаля тернарный оператор. Тот же if - then- else, только возвращающий значение. Очень логично. Был в Алгол-60 и 68, на базе которых Вирт сочинял свой Паскаль, но Вирт был сторонником минимализма, и кастрировал алголы, зачастую выплескивая ребенка вместе с водой.
Вот в питоне как раз отвратительно, потому что не симметрично. Если вы выражениях не по 1 букве (a и b) - вариант который сейчас на много читабельнее. И работает по аналогии с обычным if и с другими языками. Это только в питоне так раскорячиваться надо.
Во-первых, не надо перевирать. Запись будет иметь вид: var min := if a < b then a else b; Без дурацких скобок и с нормальным паскалевским then. Переводим на русский: “переменной min присвоить: если a < b, то a, иначе b” Все логично. А теперь переведем на русский питоновское: "min присвоить a, если a < b, иначе b.
Питон - это образец изъянений в стиле магистра Йоды: “а присвоить если a меньше b минимуму нужно иначе b”