Курс по Raku / Приложение 🆕 / Всичко наедно / Смесени мини проекти / Exercises / Решето на Ератостен

Решение: Решето на Ератостен

Ето едно възможно решение на задачата.

Код

my $limit = 30;
my %composite;

for 2 .. $limit -> $i {
    next if %composite{$i};
    for ($i², $i² + $i ... $limit) -> $multiple {
        %composite{$multiple} = True;
    }
}

say (2..$limit).grep({ !%composite{$_} });

🦋 Намерете програмата във файла sieve.raku.

Изход

(2 3 5 7 11 13 17 19 23 29)

Коментари

  1. Вместо списък от флагове, %composite помни кои числа са зачеркнати. Число, което още липсва в него, когато дойде редът му, е просто.

  2. За всяко просто $i кратните му се пораждат като последователността $i², $i² + $i ... $limit и се отбелязват като съставни. Започването от $i² прескача кратните, вече обработени от по-малки прости числа.

  3. Това е една-единствена последователност, а не заглавие на цикъл for в стил C. Операторът ... взема първите две стойности, изчислява стъпката между тях и продължава до границата. За $i = 3 това означава започване от 9, после 12, значи стъпката е 3, и цикълът обхожда целия списък:

    my $i = 3;
    say ($i², $i² + $i ... 30); # (9 12 15 18 21 24 27 30)

    Значи for получава един списък за обхождане — 9, 12, 15, …, — а не три отделни клаузи.

  4. $i² повдига числото на квадрат с горен индекс от Unicode. Raku приема и трите записа — $i * $i, $i ** 2 и $i²: те изчисляват точно една и съща стойност, така че изберете онзи, който ви се чете най-добре. Цифрите за горен индекс (², ³, …) са обикновени знаци, които можете да наберете или поставите направо в изходния код.

Навигация в курса

Решето на Ератостен   |   Оценки от редове CSV