Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Усовершенствовать алгоритм поиска.


Автор: lanD 5.6.2006, 21:32
Программа неэффективна. Например, она анализирует четные числа больше 2, хотя очевидно, что они не могут быть простыми. Усовершенствуйте алгоритм поиска простых чисел.
Код

#!/usr/bin/perl -w
$maxprimes=20; # Необходимо найти только первые 20 простых чисел
$value=1;
$count=0;
while($count < $maxprimes) {
    $value++;
    $composite=0;
OUTER: for($i=2; $i<$value;$i++) {
       for($j=$i; $j<$value; $j++) {
            if(($j*$i)==$value) {
                $composite=1;
            }
       }
}
if (! $composite) {
    $count++;
    print "Число $value простое\n";
}
}
 

Автор: igorold 6.6.2006, 08:36
Держи, студент  smile 
Код

#!/usr/bin/perl
use strict;
use DBI;

my $DebugFile;
open($DebugFile, ">>","simpl") or die("Error opening debug file\n");
use integer;

my $maxprimes=20; # Необходимо найти только первые 20 простых чисел
my $value=2;
my $count=0;
my $composite=0;
my ($i, $j);
my @simpl = (2);
my $max;
my $rez;

while($count < $maxprimes)
{
    $value++;
    $composite=1;
    $max = $value / $simpl[0];
    for ($i=0; $i<$count;$i++)
    {
        if ($simpl[$i]>$max) {last;}
        $rez = ($value/$simpl[$i])*$simpl[$i];
        if ($rez==$value)
        {
            $composite=0;
            last;
        }
        $max = $value / $simpl[$i];
    }
    if ($composite)
    {
        $count++;
        $simpl[$count] = $value;
    }
}

print $DebugFile "Простые числа: @simpl\n";

no integer;
exit(0);
1;


какие средства убыстрения поиска:
1. Формируется массив простых чисел
2. число проверяется на делитель только простого числа
3. если следующее простое число больше, чем значение/предыдущее простое число, то цикл прерывается
поясню: возьмем число 29, если оно не делиться на 2, 3, 5, то дальше деление проверяться не будет ...  
4. происходит выход из цикла проверок при нахождении первого делителя
5. можешь сделать еще одно убыстрение - после $value == 3 делать приращение +2, т.е. не проверять заведомо четные числа - попробуй сам сделать ...     

Автор: lanD 6.6.2006, 09:42
Студентка  smile
Спасибо!

Добавлено @ 09:47 
Кстати, я это задание выполняла по книге "Освой сво Perl за 24 часа"!
И я ещё не дошла до массивов :-) вот только начинаю... так что задание можно было выполнить с стандартными while, for, if.... ну и т.д. 

Автор: igorold 6.6.2006, 09:52
т.е. тебе надо сделать без массива?
тогда тебе надо использовать способы ускорения 3-5 

сделаешь без массива или тебе помочь?  smile  smile  

Кстати, увеличение на 2 я сделал так:

Код

............
while($count < $maxprimes)
{
    if ($value>=3) { $value++;}    # <---- вот эта строчка добавлена
    $value++;
    $composite=1;
.................
 

Автор: lanD 6.6.2006, 10:15
Нет спасибо ты и так помог, я уже сама дальше.
Если во время изучения у меня будут появляться кое-какие вопросы, я буду спрашивать если можно smile 

Автор: vumnik 6.6.2006, 10:40
А вот мой вариант. Тоже на делителях и без массивов.

Код

$min = 2;
$flag = 1;

while ($flag) {
    $max += 100;
    #цикл по проверяемым числам
   NEW: foreach $i ($min..$max) {
        #цикл по числам, которыми проверяем
        foreach $j (2..$i-1) {
            #есил деление по модулю даёт нам ноль хотябы в одном случае
            #то считаем число не простым и переходим на следующую итерацию
            unless ($i%$j) { next NEW; }
        }
        #если не было переходов по метке, то считаем число простым
        $count++;
        print "$count: $i\n";
        #есил нашли нужное количество простых чисел завершаем программу
        if ($count == 20) {
            $flag = 0;
            last;
        }
        last if $flag == 0;
    }
    $min = $max;
}
 

Автор: igorold 6.6.2006, 14:40
Хороший вариант, а теперь осталось только его оптимизировать ...  smile  

Автор: lanD 7.6.2006, 01:29
Нужно модифицировать программу чтобы фигурка печаталась в вертикальном положении...
Код

#!/usr/bin/perl -w

@words=qw( Интернет Ответ Принтер Программа );
$guesses[0]="";
$wrong=0;

$choice=$words[rand @words];
$hangman="0-|--<";
@letters=split(//, $choice);
@hangman=split(//, $hangman);
@blankword=(0) x scalar(@hangman);
OUTER:
    while ($wrong<@hangman) {
        foreach $i (0..$#letters) {
            if ($blankword[$i]) {
                print $blankword[$i];
            } else {
                print "-";
            }
        }
        print "\n";
        if ($wrong) {
            print @hangman[0..$wrong-1]
        }
        print "\n Ваш выбор: ";
        $guess=<STDIN>; chomp $guess;
        foreach(@guesses) {
            next OUTER if ($_ eq $guess);
        }
        $guesses[$#guesses]=$guess;
        $right=0;
        for ($i=0; $i<@letters; $i++) {
            if ($letters[$i] eq $guess) {
                $blankword[$i]=$guess;
                $right=1;
            }
        }
        $wrong++ unless($right);
        if (join('', @blankword) eq $choice) {
            print "Вы угадали! Загаданное слово было $choice\n";
            exit;
        }
    }
    print "$hangman\n Печально, но было загадано слово $choice!\n";
    

 

Автор: igorold 7.6.2006, 08:10
lanD, чтобы фигурка печаталась в вертикальном положении, т.е. каждый символ на новой строке, если я правильно понял, нужно после каждого символа фигуры вставлять (печатать) \n
т.е. строку 
Код

print @hangman[0..$wrong-1]

можно заменить на 
Код

for ($s=0;$s<$wrong;$s++) { print "$hangman[$s]\n" }

соответственно и в конце вместо
Код

print "$hangman\n Печально, но было загадано слово $choice!\n";

вставить
Код

for ($s=0;$s<$wrong;$s++) { print "$hangman[$s]\n" }
print " Печально, но было загадано слово $choice!\n";

ну и человечка переписать на 
Код

$hangman="0|-||A";

 
или так:
Код

...................
$hangman=" O !/A\\! V !J L!---";
.....................
@hangman=split(/!/, $hangman);
..................
 

Автор: sharq 7.6.2006, 09:52
igorold, 
Цитата(igorold @  7.6.2006,  09:10 Найти цитируемый пост)
for ($s=0;$s<$wrong;$s++) { print "$hangman[$s]\n" }

Ты на Perl пишешь, к чему здесь Сишные циклы? Используй foreach и постфиксную запись!

Кстати, если помогаешь человеку, то пиши код с 
Код

use strict;

Чтобы он сразу привыкал к хорошему стилю программирования на Perl.

 smile  

Автор: lanD 7.6.2006, 10:28
Вообщето я она.

Цитата(sharq @  7.6.2006,  09:52 Найти цитируемый пост)
Ты на Perl пишешь, к чему здесь Сишные циклы? Используй foreach и постфиксную запись!

Такое задание было...



Цитата(igorold @  7.6.2006,  08:10 Найти цитируемый пост)
нужно после каждого символа фигуры вставлять (печатать) \n

Так в принципе я  и делала.
Цитата(sharq @  7.6.2006,  09:52 Найти цитируемый пост)
use strict;

Я ещё незнаю даже что это такое не дошла. 

Автор: igorold 7.6.2006, 11:08
sharq, а где вы увидели, что я не пишу 
Код

use strict;
смотрим 2-й пост -> Дата 6.6.2006, 08:36

а насчет Ты на Perl пишешь, к чему здесь Сишные циклы? Используй foreach и постфиксную запись!

так я не профи ... во-вторых человеку никто не отвечал ... а я ответил ... в третьих, а что этот цикл в перле не работает?
а что такое постфиксная запись? а в 4-х на этом форуме я сам учусь ...  

Автор: sharq 8.6.2006, 17:43
lanD, советую тебе писать все свои скрипты с
Код

use strict 

igorold в первом своем примере использовал эту прагму, посмотри в чем отличие + почитай perldoc strict и можешь воспользоваться поиском, здесь уже об этом говорилось.

igorold, 
Цитата(igorold @  7.6.2006,  12:08 Найти цитируемый пост)
в третьих, а что этот цикл в перле не работает?

конечно работает, т.к. основной принцип Perl - ТимТоуди
но зачем писать на перл, не используя его возможностей.

Цитата(igorold @  7.6.2006,  12:08 Найти цитируемый пост)
а что такое постфиксная запись?

в данном случае:
Код

print "..." for ...;



Цитата(igorold @  7.6.2006,  12:08 Найти цитируемый пост)
так я не профи 

так и я тоже  smile 

 smile  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)