Версия PascalABC.NET 3.5


#209

В теории LINQ позволяет записать любой алгоритм в 1 строку. Вот только в случае простых чисел и прочих элементарных и часто вызываемых алгоритмов - лучше всё равно расписывать по старинке, потому что иначе будет огромная потеря производительности.

Ну, на всяк - приведите тот код в 1 строчку и алгоритм решета Эратосфена на старом паскале.
При переводе на новый всегда есть что улучшить, хотя бы те же for var и элементарные оптимизации для .Net, что увижу из такого - скажу.


#210

Любую программу можно в 1 строчку написать


#211

Но это кстати спорно. Вообще программа будет хотя бы 3 строчки, потому что ещё begin и end., поэтому я сказал алгоритм.

А ещё можно ли это считать 1 строчкой?))

begin
  Arr(0).ForEach(_o->begin %любой алгоритм% end);
end.

По моему это уродливое форматирование, поэтому однострочной программой лучше считать ту - в которой всего 1 end. Не begin, потому что case-end и т.п. в 1 строчку - тоже кривое форматирование.

Однако я уже не помню что за алгоритм, потому что это было давно, но однажды от нечего делать я решил записать какой то сложный алгоритм однострочным, основываясь на этом же определении (1 end на программу).

И, в общем, после пары часов говнокоденья я закончил логически доказав что всех функций Linq и PABCSystem не хватает и это невозможно написать без введения дополнительной переменной. То есть написать можно только в 2 строчки.


#212

Боюсь представить, кому такое может потребоваться, если предполагать, что реализуемый алгоритм не уровня Hello world.

Которые можно поместить в одну строку. Только, опять же вопрос - зачем?


#214

А вообще вроде вспомнил. Не тот самый алгоритм но смысл.
Вот пример не решаемой задачи:

Найдите сумму минимума и максимума массива

Как создавать массив - не важно. С клавиатуры/рандомом. Смысл в том что не сохраняя этот массив в переменную - вычислить и минимум и максимум сразу не выйдет.

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.

И даже почти работает, эх, если бы ещё не падало)))


#215

Стандартный алгоритм поиска простых чисел

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.

Длинновато по-старому…


#216

Известный еще по языку С “синдром одной строки” явление нехорошее. В программе должно быть ровно столько строк, сколько требуется, а погоня за упаковкой в строку любого алгоритма - она сущеглупое действо.


#217

Ну уже хотя бы через 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).


#218

Вот более короткое решение, которое для n = 10 млн быстрее примерно в 50 раз.

Для 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.