Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> php, нестандартная непонятная задача, "эффективный процесс" 
:(
    Опции темы
NFL
  Дата 30.11.2009, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Задали написать программу или веб-приложение, решающее следующую задачу (скрин): 
user posted image
Реально ли уложиться в условие - время выполнение 10 сек? 
Язык - желательно php, поэтому здесь и пишу... Однако, возможно и на С/С++
Натолкните на идею, если такую задачу можно решить  smile  smile 
PM MAIL   Вверх
NLspieler
Дата 30.11.2009, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 619
Регистрация: 13.10.2008
Где: Берлин

Репутация: 16
Всего: 19



Если переведешь на русский, то наверняка появятся куча советов, как решить задачу
PM MAIL   Вверх
NFL
Дата 30.11.2009, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Задача М. Эффективный процесс.

В однм из химических производств процесс производства вещества состоит из повторяемых циклов-процессов. Процесс состоит из 8 подпроцессов, которые имеют номера 1-8. Процессы должны быть запущены по одному, не ранее чем через один интервал времени Т. Подпроцессы имеют различную длительность, возможности совмещения во времени. условия запуска, согласно таблицы (на скрине)
Эффективность процесса оцениваем показателем эффективности, который рассчитываем как разность между показателем качества вещества, который без нарушения условий равен 8, а каждое нарушение условий отнимает 1.5 и показателем длительности процесса, который равен длительности подпроцесса в количестве интервалов Т, деленной на 5. Программа должна напечатать 2 лучших последовательности номеров подпроцессов и их показатели .

ввод можно сделать с клавы, если что, в принципе, это все и сам сделаю, интересует именно принцип пересчета этих гребанных показателей...

что обозначают условия запуска подпроцесса: если, например, стоит условие "-5", то это значит что подпроцесс должен быть запущен перед подпроцессом №5, а положительное число - подпроцесс должен быть запущен после подпроцесса с указанным номером.
PM MAIL   Вверх
awdev
Дата 1.12.2009, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 22.11.2009

Репутация: 1
Всего: 1



Воник вопрос, запускаем мы 6й процесс который совместим с 3м.

На втором шаге мы запускаем 3й процесс, который совместим с 6.

На третем шаге что? Другие процессы не совместимы? Ждем ?

Если ждем, тогда о каких нарушениях идет речь в условиях? Если не ждем, то нарушаем процесс ? или как?


PM MAIL   Вверх
NFL
Дата 1.12.2009, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



awdev, 
условия: (-8) - процесс должен быть запущен после 8-го, (5) - перед 5-м. 

На совместимость можно забить, проверял вручную, что с ней, что без нее, результаты те же. то есть, суть в том, чтобы выбрать все числа из диапазона 12345678-88888888, в которых нет нарушения условий совместимости, и потом  с ними уже посчитать показатель эффективности...
но перебор банальным for($i=12345678; $i<88888889;$i++){}
это зло, в 10 сек не уложится ни за что...
PM MAIL   Вверх
Simpliest
Дата 1.12.2009, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



NFL, 
у тебя 8! перестановок с учетом ограничений еще меньше.
Цикл тебе нужен по перестановкам. И 40к комбинаций уложить в 10с более чем реально



--------------------
user posted image
PM   Вверх
NFL
Дата 1.12.2009, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Simpliest, пример можно? smile что то туплю...
PM MAIL   Вверх
Simpliest
Дата 1.12.2009, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



12345678
21345678
23145678
...
87654321


--------------------
user posted image
PM   Вверх
NFL
Дата 1.12.2009, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Simpliest, не... я о примере кода, как регулярку или что прописать?
чтоб получить, например, массив или еще что то из нужных мне значений... 
зы: делаю без повторений, тоесть, 40320 комбинаций надо перебрать...


PM MAIL   Вверх
sTa1kEr
Дата 2.12.2009, 00:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Не совсем ясны условия задачи.
1. То что подпроцессы могут быть совмещены по времени - это означает, что совместимые подпроцессы могут быть запущены одновременно (т.е. суммарное время их выполнения всегда равно max(T1, T2))? Или же все-таки учитывается  условие, что подпроцесс может быть запущен не ранее чем через 1 ед. времени (т.е. суммарное время max(T1,T2+1) или max(T2,T1+1) в зависимости от порядка)?
2. Условие запуска означает, что подпроцесс должен быть выполнен непосредственно перед/после указанного подпроцесса? Или же между ними могут быть выполнены другие подпроцессы без нарушения условия процесса?
3. Могут ли быть взаимнопротиворечащие друг другу условия? Т.е. когда в принципе невозможно завершить процесс без нарушения хотя бы одного условия?
4. Пример в задаче какой-то совсем абсурдный, даже если исправить опечатки и предположить, что взаимнопротиворечащие условия возможны, то все равно как не крути, но эффективность 3.4 для первой строки и 3.3 для второй ну никак не получается.

Цитата(Simpliest @  1.12.2009,  10:24 Найти цитируемый пост)
Цикл тебе нужен по перестановкам

Это не интересно smile 

Цитата(Simpliest @  1.12.2009,  10:24 Найти цитируемый пост)
И 40к комбинаций уложить в 10с более чем реально

Я думаю, что тут суть не в том, что бы уложить решение задачи во времени в 10с, а в том, что бы найти более оптимальный алгоритм, нежели полный перебор всех возможных вариантов.

Это сообщение отредактировал(а) sTa1kEr - 2.12.2009, 00:57
PM MAIL   Вверх
NFL
Дата 2.12.2009, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



sTa1kEr, 

1.  max(T1,T2+1) или max(T2,T1+1
2. Нет. Главное, чтобы именно перед или после.
3. Нет
4. Ну у меня 3.4 получилось, а 3.3 тоже никак(

Ну да это не важно, что там в примере, главное чтоб хоть как то считал... Хотя бы саму идею в коде, ибо я вообще в шоке от задачи(=)
PM MAIL   Вверх
Simpliest
Дата 2.12.2009, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



NFL, 
Найти все комбинации

Добавлено через 1 минуту и 58 секунд
Цитата(sTa1kEr @  1.12.2009,  23:30 Найти цитируемый пост)
что бы найти более оптимальный алгоритм, нежели полный перебор всех возможных вариантов.

Не прикалывайся. 
Я за свою недолгую жизнь не смог придумать ни одного нового алгоритма. Максимум заново открывал уже существующие.


--------------------
user posted image
PM   Вверх
sTa1kEr
Дата 2.12.2009, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(Simpliest @  2.12.2009,  14:11 Найти цитируемый пост)
Я за свою недолгую жизнь не смог придумать ни одного нового алгоритма. Максимум заново открывал уже существующие. 

Не важно, придумаешь ли ты новый алгоритм, или найдешь готовый, главное что бы он был наиболее оптимальным для конкретной задачи. Или ты считаешь метод перебора всех возможных комбинация самым оптимальным для данной задачи?

Добавлено через 2 минуты и 26 секунд
Цитата(NFL @  2.12.2009,  13:55 Найти цитируемый пост)
2. Нет. Главное, чтобы именно перед или после.

Это сильно упрощает задачу, но тогда пример в задаче совершенно не корректен.
PM MAIL   Вверх
Simpliest
Дата 3.12.2009, 06:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(sTa1kEr @  2.12.2009,  20:37 Найти цитируемый пост)
Или ты считаешь метод перебора всех возможных комбинация самым оптимальным для данной задачи?

Не всех возможных, а всех разрешеных.

Но, да.
Для задачи "найти оптимальный вариант из всех комбинаций", полный перебор будет единственным вариантом.


--------------------
user posted image
PM   Вверх
sTa1kEr
Дата 3.12.2009, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(Simpliest @  3.12.2009,  07:49 Найти цитируемый пост)
Не всех возможных, а всех разрешеных.

Разрешены абсолютно все комбинации.

Цитата(Simpliest @  3.12.2009,  07:49 Найти цитируемый пост)
Для задачи "найти оптимальный вариант из всех комбинаций", полный перебор будет единственным вариантом.

Да неужели? Я уже вижу как можно решить задачу с перебором в лучшем случае только двух вариантов smile 

Это сообщение отредактировал(а) sTa1kEr - 3.12.2009, 07:26
PM MAIL   Вверх
NewDima
Дата 5.12.2009, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



Если задача все-таки в переборе всех перестановок, то вот класс, реализующий интерфейс Iterator
Код

class Replacement implements  Iterator {
    protected $key = 0;
    protected $value = null;
    public function __construct($n) {
        $this->length = ((int)$n < 1)?1:(int)$n;
        $this->value = range(1, $this->length);
    }
    public function current() {
        return $this->value;
    }
    public function key() {
        return $this->key;
    }
    protected function __bur($el, $arr) {
        $got = max($arr);
        foreach ($arr as $value) {
            if (ord($value) > ord($el) &&
                ord($value) < ord($got)) {
                $got = $value;
            }
        }
        return array_merge(array($got), self::sort(array_merge(array_diff($arr, array($got)), array($el))));
    }
    public function sort($arr) {
        sort($arr);
        return $arr;
    }
    public function rsort($arr) {
        rsort($arr);
        return $arr;
    }
    public function nextFor($arr) {
        if (self::rsort($arr) === $arr) {
            return false;
        } else {
            if (count($arr) == 2) {
                return array_reverse($arr);
            }
            $first = array_shift($arr);
            if (false !== ($subnext = self::nextFor($arr))) {
                return array_merge(array($first), $subnext);
            } else {
                return self::__bur($first, $arr);
            }
        }
    }
    public function next() {
        $this->value = self::nextFor($this->value);
        ++$this->key;
    }
    public function rewind() {
        $this->value = range(1, $this->length);
        $this->key = 0;
    }
    public function valid() {
        return $this->value !== false;
    }
}

Использование:
Код

$rep = new Replacement(8);
$i = 0;
foreach ($rep as $value) {
    echo implode('', $value) . '<br />';
    $i++;
}
echo $i;


Добавлено через 8 минут и 52 секунды
Плюс класса в том, что никакого массива реально не создается, но значения можно получить по порядку.
Если увидите косяки, сделайте замечания, писал, чтобы размяться
PM ICQ   Вверх
sTa1kEr
Дата 5.12.2009, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Код

$rep = new Replacement(8);
$i = 0;
$time = microtime(true);
fwrite(STDOUT, "\n");
foreach ($rep as $value) {
    //echo implode('', $value) . '<br />';
    if ($i % 100 == 0) {
        fwrite(STDOUT, "\r".$i);
    }
    $i++;
}
fwrite(STDOUT, "\nOK. ".(microtime(true) - $time)."\n");

Цитата

40300
OK. 70.312089920044  smile 


Добавлено через 5 минут и 5 секунд
Нет, класс грамотно написан. Просто метод полного перебора тут ну никак не подходит.

Добавлено через 8 минут и 13 секунд
Хотя операций с массивами что-то многовато...
PM MAIL   Вверх
Simpliest
Дата 5.12.2009, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(sTa1kEr @  5.12.2009,  13:05 Найти цитируемый пост)
40300
OK. 70.312089920044

да вы гоните.


--------------------
user posted image
PM   Вверх
sTa1kEr
Дата 5.12.2009, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Нет, тут однозначно проще при помощи рекурсии перебор делать.

Добавлено через 1 минуту и 12 секунд
Цитата(Simpliest @  5.12.2009,  15:13 Найти цитируемый пост)
да вы гоните. 

Это результат, который получился на моем компе. Класс NewDima я скопировал один в один.
PM MAIL   Вверх
Simpliest
Дата 5.12.2009, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(sTa1kEr @  5.12.2009,  13:14 Найти цитируемый пост)
Это результат, который получился на моем компе. Класс NewDima я скопировал один в один. 

Да я вроде как не возражаю. 
Но такие результаты - значит конкретная реализация не годится.
Блин, сейчас сяду посмотрю


--------------------
user posted image
PM   Вверх
NewDima
Дата 5.12.2009, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



Не понял, почему 40300
результат
40320:2.52513289452 
Вполне сносный результат
PM ICQ   Вверх
Simpliest
Дата 5.12.2009, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Так, ну во-первых, этот же код у меня выполнился за  
40300
OK.  2.217719078064

sTa1kEr, что у тебя за машина?

Во-вторых, буду смотреть дальше.


--------------------
user posted image
PM   Вверх
NewDima
Дата 5.12.2009, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



Core 2 Duo E8500 3,16Ghz 3,25 ОЗУ
PM ICQ   Вверх
Simpliest
Дата 5.12.2009, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(NewDima @  5.12.2009,  13:29 Найти цитируемый пост)
почему 40300

потому что у него данные выводятся каждые 100 тактов цикла


--------------------
user posted image
PM   Вверх
NewDima
Дата 5.12.2009, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



Полагаю, какие-то методы ведут себя по-разному в разных версиях php?
У меня правильное количество результатов и я их посматривал smile

Добавлено через 14 секунд
Понял, не заметил
PM ICQ   Вверх
sTa1kEr
Дата 5.12.2009, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Вот мой вариант на скорую руку:
Код

function bruteforce($array, $result = array()) {
    static $count = 0;

    for ($i = 0; $i < count($array); $i++) {
        $n = array_shift($array);
        
        if (count($array) > 0) {
            bruteforce($array, $result + array($n => $n));
        } else {
            //echo implode('', $result).$n."\n";
            $count++;
        }
        
        array_push($array, $n);
    }

    return $count;
}

$time = microtime(true);
$count = bruteforce(range(1, 8));
echo "Completed. ".$count." iterations. ".(microtime(true) - $time)." sec\n";
// Completed. 40320 iterations. 12.601891994476 sec



Это сообщение отредактировал(а) sTa1kEr - 5.12.2009, 15:16
PM MAIL   Вверх
NewDima
Дата 5.12.2009, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



Completed. 40320 iterations. 0.307599067688 sec
PM ICQ   Вверх
sTa1kEr
Дата 5.12.2009, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(Simpliest @  5.12.2009,  15:31 Найти цитируемый пост)
sTa1kEr, что у тебя за машина?

AMD Athlon™ X2 Dual Core Processor BE-2400 Вообще-то у меня netbeans компилиться smile 

Но это все не имеет значения, т.к.
1. Мы не знам на каком компе будет выполнятся программа, вполне вероятно, что задача составлялась когда еще БК'шки были
2. Преподаватель всегда может сказать: "ну ок, а теперь сделай то же самое для 12 процессов"

Добавлено через 9 минут и 43 секунды
Блин, AMD - ### =\
PM MAIL   Вверх
NewDima
Дата 5.12.2009, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



sTa1kEr, сижу и не могу сообразить, как вашим скриптом вывести генерируемые значения по порядку?
PM ICQ   Вверх
sTa1kEr
Дата 5.12.2009, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Соррь, не большой баг. Не подумал, что array_merege объединяет по ключу

Добавлено через 2 минуты и 46 секунд
Исправил 
bruteforce($array, $result + (array)$n);
на 
bruteforce($array, $result + array($n => $n));
PM MAIL   Вверх
NewDima
Дата 5.12.2009, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



Мне удалось согнать мой вариант только до 1.60964894295 =(

Добавлено через 28 секунд
при вашем 0.521440029144 
PM ICQ   Вверх
Simpliest
Дата 5.12.2009, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(sTa1kEr @  5.12.2009,  14:15 Найти цитируемый пост)
Соррь, не большой баг. Не подумал, что array_merege объединяет по ключу

Все это фигня. Там сам подсчет эффективности достаточно замороченный smile

Добавлено через 7 минут и 20 секунд
Цитата(NewDima @  5.12.2009,  14:33 Найти цитируемый пост)
Мне удалось согнать мой вариант только до 1.60964894295 =(

user posted image


--------------------
user posted image
PM   Вверх
sTa1kEr
Дата 5.12.2009, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(NewDima @  5.12.2009,  16:33 Найти цитируемый пост)
Мне удалось согнать мой вариант только до 1.60964894295 =(

Раз так, то я тоже оптимизировал слегка smile 
1. Убрал статическую переменную
2. Вынес в переменную count($array)
3. Поменял местами if и for, что бы сэкономить на проверке внутри цикла
4. Заменил счетчик мз цикла $total++, на $total += $count вне цикла.. Был не прав. В связи с п.3 - это уже не нужно, заменил на return $count; Почему не на return 1? Можно было бы и так, но в случае return $count PHP не придется создавать дополнительную переменную, что бы вернуть 1.
Я тормоз... Там вообще цикл не нужен... Все, теперь конечный вариант.

Итого:
Код

function bruteforce($array, $result = array()) {
    $total = 0;
    $count = count($array);

    if ($count > 1) {

        for ($i = 0; $i < $count; $i++) {
            $n = array_shift($array);
            $total += bruteforce($array, $result + array($n => $n));
            array_push($array, $n);
        }

    } else {

        //echo implode('', $result).$array[0]."\n";
        return $count;
    }

    return $total;
}



NewDima, если не сложно, проверь какой теперь у тебя результат?

Добавлено @ 15:59
Цитата(Simpliest @  5.12.2009,  16:46 Найти цитируемый пост)
Все это фигня. Там сам подсчет эффективности достаточно замороченный smile

Извини, не понял, что ты этим хотел сказать?

Добавлено @ 16:01
Цитата(Simpliest @  5.12.2009,  16:46 Найти цитируемый пост)
Все это фигня. Там сам подсчет эффективности достаточно замороченный smile

Из-за этого бага, если разкомментировать echo, выводилось только последние 2 цифры.

Это сообщение отредактировал(а) sTa1kEr - 5.12.2009, 16:12
PM MAIL   Вверх
NewDima
Дата 5.12.2009, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 10
Всего: 12



отлично  smile 
Completed. 40320 iterations. 0.249315023422 sec

Добавлено через 1 минуту и 50 секунд
В моем варианте время выполнения скрипта растет просто бешеными темпами при увеличении размера массива, так-что какашка у меня=(
PM ICQ   Вверх
sTa1kEr
Дата 5.12.2009, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Еще одно место оптимизировал, убрал второй цикл smile  

Все, больше не знаю, что еще можно оптимизировать... Если увидите, скажите smile 
PM MAIL   Вверх
Simpliest
Дата 5.12.2009, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(sTa1kEr @  5.12.2009,  14:57 Найти цитируемый пост)
Извини, не понял, что ты этим хотел сказать?

я про рассчет эффективности комбинации согласно задаче ТС smile

Цитата(NewDima @  5.12.2009,  15:06 Найти цитируемый пост)
так-что какашка у меня=( 

Я дал профайлинг. посмотри методы которые вызываются по 273к раз
один из них сортировка smile


--------------------
user posted image
PM   Вверх
sTa1kEr
Дата 5.12.2009, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Все... вот последняя экстримальная оптимизация за счет уменьшения рекурсии на 2уровня и ухудшения читабельности smile  :
Так
Код

function bruteforce($array, $result = array()) {
    $total = 0;
    $count = count($array);

    if ($count == 3) {

        $return = implode('', $result);

        //echo $return.$array[0].$array[1].$array[2]."\n";
        //echo $return.$array[0].$array[2].$array[1]."\n";
        //echo $return.$array[1].$array[2].$array[0]."\n";
        //echo $return.$array[1].$array[0].$array[2]."\n";
        //echo $return.$array[2].$array[0].$array[1]."\n";
        //echo $return.$array[2].$array[1].$array[0]."\n";

        return 6;

    } else if ($count > 3) {

        for ($i = 0; $i < $count; $i++) {
            $n = array_shift($array);
            $total += bruteforce($array, $result + array($n => $n));
            array_push($array, $n);
        }
    } else {

        throw new RuntimeException('Array must be have 3 or more elements');

    }

    return $total;
}


Добавлено через 5 минут и 46 секунд
Да... этот метод даже на моем тормазнутом AMD'шнике меньше секунды выполняется...
Но это все равно не true way!  smile 
PM MAIL   Вверх
NFL
Дата 5.12.2009, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



тааак, с перебором понятно smile 
что с эффективностью то делать?
я с ней вообще не пойму... превращать каждое в строку и проверять посимвольно?
PM MAIL   Вверх
Simpliest
Дата 5.12.2009, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 625
Регистрация: 1.9.2009

Репутация: 1
Всего: 3



Цитата(NFL @  5.12.2009,  21:01 Найти цитируемый пост)
что с эффективностью то делать?

Бггг, я же говорил smile


--------------------
user posted image
PM   Вверх
NFL
Дата 5.12.2009, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Simpliest, что то тему прочитал видимо невнимательно smile 
ща перечитаю smile 
PM MAIL   Вверх
sTa1kEr
Дата 5.12.2009, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



В общем, я от нечего делать добил твою задачу smile Комментировать было лень

Код

class Sub {
    public $id;
    public $time;
    public $bonus;
    public $compatible;
    public $depends;
    public $input;
    public $placed;
    
    public function __construct($input) {
        $this->input = $input;
        $this->id = $this->input[0];
        $this->time = $this->input[1] * Process::RATIO;
    }

    public function reset() {
        $this->bonus = 0;
        $this->compatible = null;
        $this->depends = array();
        $this->placed = false;
    }

    public function compatible($proc) {
        $this->compatible = $proc;
        $this->bonus = $proc->time + $this->time - max($proc->time, $this->time + Process::RATIO);
    }

    public function condition($proc, $left = false) {
        if ($left) {
            $this->depends[] = $proc;
        } else {
            $proc->depends[] = $this;
        }
    }

    public function __toString() {
        return (string)$this->id;
    }
}

class Process {
    const QUALITY = 8;
    const PENALTY = 1.5;
    const RATIO = 0.2;

    protected $processes = array();
    protected $result;
    protected $nominalTime;
    protected $best;

    public function __construct(array $input) {
        foreach ($input as $val) { $this->processes[$val[0]] = new Sub($val); }
    }

    public function run($profile = false) {
        $time = microtime(true);
        $this->prepare();
        $count = $this->bruteforce($this->processes);

        if ($profile) { 
            printf("Iterations: %s; Time: %0.4f\n", $count, microtime(true) - $time);
        }

        return $this->result;
    }

    public function test($string) {
        $processes = array();
        foreach (explode(' ', $string) as $id) {
            $processes[] = $this->processes[(integer)$id];
        }

        $this->prepare();
        $this->calc($processes);
        return $this->result;
    }

    protected function calc($processes) {
        $quality = self::QUALITY;
        $time = $this->nominalTime;
        $prev = null;

        foreach ($processes as $proc) { $proc->placed = false; }
        foreach ($processes as $proc) {
            $proc->placed = true;

            if ($proc->compatible === $prev)  { $time -= $proc->bonus; }

            foreach ($proc->depends as $depend) {
                if (!$depend->placed) { $quality -= self::PENALTY; }
            }

            $prev = $proc;
        }

        $effectiveness = $quality - $time;
        if ($effectiveness >= $this->best) {
            $this->best = $effectiveness;

            array_unshift($this->result, array($effectiveness, $processes));

            if (count($this->result) > 2) {
                array_pop($this->result[2]);
            }
        }
    }

    protected function prepare() {
        $this->nominalTime = 0;
        $this->best = 0;
        $this->result = array();
        
        foreach ($this->processes as $proc) {
            $proc->reset();
            $this->nominalTime += $proc->time;

            if ($proc->input[2] > 0) {
                $proc->compatible($this->processes[$proc->input[2]]);
            }

            if ($proc->input[3] != 0) {
                $proc->condition($this->processes[abs($proc->input[3])], $proc->input[3] < 0);
            }
        }
    }
    
    protected function bruteforce($processes, $result = array()) {
        $total = 0;
        $count = count($processes);

        if ($count == 1) {

            $this->calc($result + array($processes[0]->id => $processes[0]));
            return 1;

        } else {

            for ($i = 0; $i < $count; $i++) {
                $proc = array_shift($processes);
                $total += $this->bruteforce($processes, $result + array($proc->id => $proc));
                array_push($processes, $proc);
            }

        }
        
        return $total;
    }
}

Код

$process = new Process(array(
    array(1, 2, 2, -8),
    array(2, 1, 1, 0),
    array(3, 4, 6, 5),
    array(4, 4, 8, 0),
    array(5, 1, 0, 0),
    array(6, 7, 3, 0),
    array(7, 2, 0, 0),
    array(8, 3, 4, 5)
));

$result = $process->run(true);
echo implode(' ', $result[0][1]).'  '.$result[0][0]."\n";
echo implode(' ', $result[1][1]).'  '.$result[1][0]."\n";

Код

Iterations: 40320; Time: 0.8913
7 6 3 4 8 5 1 2  4.8
7 6 3 4 8 1 2 5  4.8

Если использовать вместо класса Sub массив, то можно увеличить производительность на ~20-30%

Можно будет на досуге решить ее алгоритмом без перебора.
PM MAIL   Вверх
NFL
Дата 5.12.2009, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



sTa1kEr, спс огромное, преподу хватит smile  smile  smile 
PM MAIL   Вверх
sTa1kEr
Дата 5.12.2009, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Пара не очевидных моментов:

Sub::$depends - это процессы, которые по условию должны предшествовать текущему процессу
Sub::$bonus - это время, которое мы экономим, если предшествует совместимый процесс
Process:$nominalTime - это время, затрачиваемое на процесс без учета совместимости процессов

Для максимально быстрого расчета эффективности, мы из номинального времени вычитываем бонусное (если процессы совпали) и из качества штраф за несоблюдение условия.

Добавлено через 1 минуту и 18 секунд
Цитата(NFL @  6.12.2009,  00:01 Найти цитируемый пост)
sTa1kEr, спс огромное, преподу хватит       

Я не для препода ее решал, а для себя smile Так сказать разминка для мозгов smile 
PM MAIL   Вверх
NFL
Дата 5.12.2009, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



sTa1kEr,  smile  smile 

да ну его, для себя такие задачи решать, никому не нужные smile 
PM MAIL   Вверх
sTa1kEr
Дата 5.12.2009, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(NFL @  6.12.2009,  00:10 Найти цитируемый пост)
да ну его, для себя такие задачи решать, никому не нужные

Сама по себе задача может быть и никому не нужная, но мышление такие задачи развивают очень хорошо. 

Кстати, как можно легко доработать этот алгоритм, что-бы сократить перебор, в лучшем случае, до 2х итераций в независимости от количества процессов.
Так как мы знаем "бонусы" для всех процессов и номинальное время, то можем легко высчитать так же минимально возможное время. Т.о. если вычесть из номинального качества минимальное время, мы получим максимально возможную эффективность.
А так как условие задачи - найти последовательности с максимальной эффективностью, то нам достаточно сравнивать полученную эффективность с максимальной и, если они равны, то завершить перебор, т.к. дальнейшей перебор уже не имеет смысла.
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0984 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.