[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: кто хочет размять мозги?
MatrixGod
всем привет!

есть задачка:
надо написать функцию которая принимает целое число $n и возвращает или печатает такую вот последовательность: 1, 2, 3, ..., $n, ..., 3, 2, 1.
например для числа 5 она выдаст: 1, 2, 3, 4, 5, 4, 3, 2, 1.
нельзя пользоваться циклами. надо реализовать только с помощью рекурсии.

кто желает помочь а заодно потрясти мозгами?

заранее биг сенкс!



Спустя 12 минут, 11 секунд (15.11.2010 - 20:12) waldicom написал(а):
Возьмите пример факториала и дальше по аналогии

Спустя 2 минуты, 3 секунды (15.11.2010 - 20:14) twin написал(а):
Не нужна тут рекурсия. И циклы не нужны. Задача решается в три строчки штатными функциями.

Спустя 6 минут, 24 секунды (15.11.2010 - 20:21) MatrixGod написал(а):
waldicom
факториал это слишком просто. но в этой задачке есть некий математический трюк. я никак не могу до него додуматься... не поможешь?

Спустя 12 минут, 9 секунд (15.11.2010 - 20:33) twin написал(а):
function example($n)
{
$arr = range(1, $n);
$last = array_reverse(range(1, $n - 1));
return implode(',', array_merge($arr, $last));
}

echo example(5);

Спустя 12 минут, 6 секунд (15.11.2010 - 20:45) MatrixGod написал(а):
twin
спасибо за старания. но требуется именно рекурсия...

Спустя 13 минут, 17 секунд (15.11.2010 - 20:58) waldicom написал(а):
Цитата (twin @ 15.11.2010 - 19:14)
Не нужна тут рекурсия.

Странно. Топикстартер утверждает, что ему нужно, а ты говоришь нет... Кто же из вас прав...

Спустя 7 минут, 4 секунды (15.11.2010 - 21:05) MatrixGod написал(а):
неужели никто не раскусит? мозг уже потек от этой задачки...

Спустя 3 минуты, 9 секунд (15.11.2010 - 21:08) twin написал(а):
Цитата
Странно. Топикстартер утверждает, что ему нужно, а ты говоришь нет... Кто же из вас прав...

Ну нужно, так нужно. Не вопрос.

По крайней мере задача решается без рекурсии и делать как то иначе лично я не вижу никакого практического смысла.

Спустя 5 минут, 41 секунда (15.11.2010 - 21:14) MatrixGod написал(а):
twin
практического смысла и нет. это задачка с моего курса по оптимизации алгоритмов.
и надо, хоть убейся, написать именно через рекурсию. ну такова задача.

вообще-то я пишу этот алгоритм на языке "си". но тут дело не в языке а в самом алгоритме. не знаю как его составить...

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

Спустя 1 минута, 29 секунд (15.11.2010 - 21:16) Invis1ble написал(а):
MatrixGod
Держи рекурсию )
  function fn($int, $i)
{
if ($i >= $int - 4 && $i <= $int + 4)
echo $i.' ';
elseif ($i > $int + 4)
die('<br />Готово');

$i ++;
fn($int, $i);
}

$int = 10;
$i = 1;

fn($int, $i);

Спустя 9 минут (15.11.2010 - 21:25) MatrixGod написал(а):
Invis1ble
не-а, не дает... sad.gif
к тому же функция должна принимать только 1 аргумент...

Спустя 2 минуты, 15 секунд (15.11.2010 - 21:27) Invis1ble написал(а):
MatrixGod
что не дает? )

Спустя 1 минута, 1 секунда (15.11.2010 - 21:28) Invis1ble написал(а):
MatrixGod
а, все понял... я тз невнимательно прочитал просто )

Спустя 12 секунд (15.11.2010 - 21:28) MatrixGod написал(а):
Invis1ble
печатает что-то не то...

Спустя 14 минут, 10 секунд (15.11.2010 - 21:42) kirik написал(а):
Вот рабочая и с одним аргументом на входе:
function fn($i, $to = false) {
if($to === false) { // если первый запрос функции
$to = $i;
$i = 1;
} elseif($i == 0 && $to == 1) { // прерываем рекурсию
return;
} elseif($to == $i) { // дошли до середины
$to = 1;
}
echo ($i < $to ? $i++ : $i--) . ($i > 0 ? ',' : '');
fn($i, $to);
}


fn(5);

Спустя 8 минут, 7 секунд (15.11.2010 - 21:50) Invis1ble написал(а):
kirik
опередил меня малехо..

Спустя 8 минут, 12 секунд (15.11.2010 - 21:58) waldicom написал(а):
Цитата (kirik @ 15.11.2010 - 20:42)
Вот рабочая и с одним аргументом на входе:

С нулем не работает, а так классное решение. Как и от Твина, если без рекурсии.

Спустя 3 минуты, 16 секунд (15.11.2010 - 22:02) MatrixGod написал(а):
kirik
спасибо огромное! как раз то что надо!

Спустя 26 минут, 36 секунд (15.11.2010 - 22:28) kirik написал(а):
Цитата (waldicom @ 15.11.2010 - 13:58)
С нулем не работает, а так классное решение.

Гм.. не думал. Вот пропатченная функция:
function fn($i, $to = false) {
if($to === false) { // если первый запрос функции
if($i <= 0) { // защита от waldicom'а :)
echo 0;
return;
}
$to = $i;
$i = 1;
} elseif($i == 0 && $to == 1) { // прерываем рекурсию
return;
} elseif($to == $i) { // дошли до середины
$to = 1;
}
echo ($i < $to ? $i++ : $i--) . ($i > 0 ? ',' : '');
fn($i, $to);
}


UPD:
Так лучше, без лишнего if'а:
function fn($i, $to = false) {
if($to === false) { // если первый запрос функции
$to = $i;
$i = 1;
} elseif($i <= 0) { // прерываем рекурсию если 0 или меньше
return;
} elseif($to == $i) { // дошли до середины
$to = 1;
}
echo ($i < $to ? $i++ : $i--) . ($i > 0 ? ',' : '');
fn($i, $to);
}

Спустя 8 минут, 28 секунд (15.11.2010 - 22:37) SlavaFr написал(а):
error_reporting(E_ALL);

function tuda_obratno($chislo,$sejchas=1,$napravlenie=1,$buf=''){
if($sejchas==0 && $napravlenie < 0 ){
echo $buf; //это работает
return $buf;//но почему ретурн не получается?
}
if($chislo==$sejchas){
$napravlenie=-1;
}
$buf.=($sejchas==1 && $napravlenie==1)?$sejchas:','.$sejchas;
tuda_obratno($chislo,$sejchas+$napravlenie,$napravlenie,$buf);
return;
}
$a= tuda_obratno(12);

var_dump($a);

exit;


немогу не хрена понять почему $а у меня == NULL
наверное я перегрелся.
т.е echo перед ретурном работает, а ретурн не чего не выдает. :blink:

Спустя 10 минут (15.11.2010 - 22:47) kirik написал(а):
SlavaFr
так у тебя функция ничего не возвращает (точнее тот самый null): return;

Спустя 4 минуты, 47 секунд (15.11.2010 - 22:52) SlavaFr написал(а):
так меня и удевляет, что
echo $buf; работает а ретурн $buf нет.

у меня дома на viste xdebug глючит. Завтра на работе через дебугер запущу.

Спустя 8 минут, 58 секунд (15.11.2010 - 23:01) kirik написал(а):
Цитата (SlavaFr @ 15.11.2010 - 14:52)
так меня и удевляет, что
echo $buf; работает а ретурн $buf нет.

Еще раз - у тебя функция ничего не возвращает, я про функцию, которую ты первый раз запрашиваешь. Возвращает только N'ная по счету, но этот return никак не передается функциям что стояли выше по рекурсии. Чтобы заработало замени
	 tuda_obratno($chislo,$sejchas+$napravlenie,$napravlenie,$buf);
return;

на
      return tuda_obratno($chislo,$sejchas+$napravlenie,$napravlenie,$buf);

Спустя 9 минут, 22 секунды (15.11.2010 - 23:10) SlavaFr написал(а):
фух @kirik спасибо. таки перегрелся я
<?php
error_reporting(E_ALL);

function tuda_obratno($chislo,$sejchas=1,$napravlenie=1,&$buf=''){
if($sejchas==0 && $napravlenie < 0 ){
return $buf;
}
if($chislo==$sejchas){
$napravlenie=-1;
}
$buf.=($sejchas==1 && $napravlenie==1)?$sejchas:','.$sejchas;
return tuda_obratno($chislo,$sejchas+$napravlenie,$napravlenie,&$buf);

}
echo tuda_obratno(8);

exit;

?>

Спустя 34 минуты, 19 секунд (15.11.2010 - 23:44) kovaldm написал(а):
Я так сделал.

function fn($i)
{
global $str;
$j = $i;
if($j>1)
{
$j--;
$str = $str . $j;
fn($j);
}

return strrev($str) . $i . $str;
}

Спустя 8 минут, 29 секунд (15.11.2010 - 23:53) kirik написал(а):
Цитата (kovaldm @ 15.11.2010 - 15:44)
Я так сделал.

Не совсем укладывается в условия задачи.

Спустя 2 минуты, 4 секунды (15.11.2010 - 23:55) kovaldm написал(а):
А что не так?

Спустя 13 минут, 33 секунды (16.11.2010 - 00:08) kirik написал(а):
Цитата (kovaldm @ 15.11.2010 - 15:55)
А что не так?

- не используется рекурсия для создания всего диапазона чисел, а только для половины
- не кошерно работать с числами как со строками smile.gif
- не работает с числами > 10
- ну и как следствие из предыдущего пункта - нельзя добавить разделитель (запятую) между числами

Спустя 23 минуты, 31 секунда (16.11.2010 - 00:32) twin написал(а):
Меня тоже в блудняк ввели :D
function example($n)
{
if($n < 1) return;

static $i = 0, $to = '', $last = '';
$to .= ++$i . ',';

if(--$n > 0)
{
$last .= $n .',';
example($n);
return;
}

echo trim($to . $last, ',');
}

example(5);

Спустя 4 минуты, 50 секунд (16.11.2010 - 00:37) kovaldm написал(а):
Вот еще

function fn($i)
{
global $j;
$j = isset($j)?$j:0;
if($j<$i)
{
$j++;
echo $j.',';
fn($i);
}
elseif(($i == $j || $i<$j) && $i>1)
{
$i--;
echo $i;
if($i>1)echo ',';
fn($i);
}
}


fn(5);

Спустя 3 минуты, 38 секунд (16.11.2010 - 00:40) SlavaFr написал(а):
@MatrixGod настучал нам по самолюбию biggrin.gif . И пошло и поехало biggrin.gif

Спустя 1 минута, 5 секунд (16.11.2010 - 00:41) kirik написал(а):
kovaldm
если передать еденичку - выведет с запятой на конце.


Спустя 34 минуты, 3 секунды (16.11.2010 - 01:15) kovaldm написал(а):
Во как

function fn($i)
{
if($i<=0) return 0;
global $j, $arr;
$j = isset($j)?$j:1;
if($j<$i)
{
$arr[] = $j;
$j++;
fn($i);
}
elseif(($i == $j) || ($i < $j && $i>0))
{
$arr[] = $i;
$i--;
fn($i);
}

return implode(',', $arr);
}



echo fn(5);

Спустя 4 минуты, 42 секунды (16.11.2010 - 01:20) kirik написал(а):
Цитата (kovaldm @ 15.11.2010 - 17:15)
Во как

Все, я отвязался smile.gif

Спустя 3 часа, 59 минут, 53 секунды (16.11.2010 - 05:20) kirik написал(а):
Гм.. возникла идея. Никто не хочет еще круче размять мозг? Ну чтоб вообще в кашу..? smile.gif
Задача все та же, только еще условия:
- функция должна иметь только один аргумент
- функция никак не должна контактировать с внешним миром (нельзя использовать глобальные)
- функция не должна использовать статические переменные
- а также нельзя вызывать никакие функции, кроме стандартных (вызов call_user_func тоже запрещен)
Вродь так.. smile.gif
Решение есть, хоть и не такое красивое как используя все вышеперечисленное.

Спустя 3 часа, 48 минут, 4 секунды (16.11.2010 - 09:08) Michael написал(а):
У меня тоже есть решение.
Первое(любимое):
line(1,5);

function line($i, $n) {
if ($i <= $n) {
echo $i; line($i+1, $n);
if ($i < $n) echo $i;
}
}


Второе(чтобы с одним параметром):
$n = 5;
line(1);
function line($i) {
global $n;
if ($i <= $n) {
echo $i; line($i+1);
if ($i < $n) echo $i;
}
}

Спустя 1 день, 7 часов, 35 минут, 29 секунд (17.11.2010 - 16:44) kaww написал(а):
Цитата (kirik @ 16.11.2010 - 02:20)
Гм.. возникла идея. Никто не хочет еще круче размять мозг? Ну чтоб вообще в кашу..? :)

function fn ($c) {
if (!is_array($c)) {
$c = array($c-1);
if ($c[0]<1) return 0;
}
$m = $c[0]-count($c);
if ($m<1) return implode(',',array_reverse($c)).','.(count($c)+1).','.implode(',',$c);
$c[] = $m;
return fn ($c);
}

echo fn(5);

Спустя 59 минут, 34 секунды (17.11.2010 - 17:43) Guest написал(а):
мда... я мог ожидать такого от "форумчан", но kirik и twin меня поразили своими решениями...

Вообще когда в студенческих заданиях пишут "принимает один параметр" это не значит, что именно рекурсивная функция принимает один параметр. Чаще всего в таком случае пишется две функции: вторая - рекурсивная, а первая принимает один параметр и вызывает вторую, передавая ей столько параметров, сколько нужно для хорошей рекурсии.

тем не менее, отвечая на вызов kirik'a:

function recursive($k)
{
if ($k <= 1)
return array($k);
$c = array_unique(recursive($k-1));
return array_merge($c,array($k),array_reverse($c));
}

echo implode(',',recursive(5));

Спустя 4 минуты, 19 секунд (17.11.2010 - 17:47) Guest написал(а):
и чуть более быстрый вариант:

function recursive($k)
{
if ($k <= 1)
return array($k);
$c = array_slice(recursive($k-1),0,$k-1);
return array_merge($c,array($k),array_reverse($c));
}

echo implode(',',recursive(5));

Спустя 41 минута, 26 секунд (17.11.2010 - 18:29) Guest написал(а):
до кучи вариант с опциональным полем (тот что ожидался от "экспертов"):

function recursive($k,$base=1)
{
if ($k <= $base)
return $k;
return $base.','.recursive($k,$base+1).','.$base;
}

echo recursive(5);
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.