Счетчик рекурсией

sloker

Новичок
Ну никак не могу написать счетчик такого вида (обязательно с помощью рекурсии):

001
002
003
010
011
012
013
100
101
102
103
110
111
112
113

Как видно на каждое число свое ограничение. Получается массив array(2, 1, 3) с максимальными значениями.

Обязательно нужна рекурсия вместо:
for ($i = ...) {
for ($j = ...) {
for ($k = ...) {
...
}
}
}

Вот код (но он неправильный, поэтому и обращаюсь за помощью):

PHP:
<?php
function timer($limit, $mas, $number) {
    $fromLimit = $limit[$number];
    for ($i = 0; $i < $fromLimit + 1; $i++) {
        $masCopy = $mas;
        $masCopy[$number] = $i;
        echo "number = $number, ";
        echo "i = $i, ";
        echo "fromLimit = $fromLimit\n";
        if ($i <= $fromLimit) {
            echo implode(", ", $masCopy)."\n";
        } else {
            echo "Рекурсия\n";
            echo implode(", ", $masCopy)."\n";
            timer($limit, $mas, $number - 1);
        }
    }
    return;
}
timer(array(2, 1, 3), array(0, 0, 0), 2);
 

sloker

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

AnrDaemon

Продвинутый новичок
Ладно, предположим, что условие описано правильно (из примера неочевидно, что там про третий разряд в условии сказано.)
Сама функция черезчур усложнена. Используются массивы там, где не надо. И не удовлетворяет условию "рекурсия". У вас там итерация идёт по одному разряду, а не рекурсия.
Пожалуй, напишу ответ (вариант ответа), но только потому, что задачка меня заинтересовала.
 

sloker

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

AnrDaemon

Продвинутый новичок
Чтобы не было бесконечной рекурсии, надо определять условия выхода.
PHP:
<?php

$limits = array(4, 2, 3);
$break = false;

function timer($set = null, $state = null, $digit = 0)
{
  global $limits, $break;

  if($digit >= count($limits))
  {
    $break = true;
    return $state;
  }

  $_add = floor(($state[$digit] + $set) / $limits[$digit]);
  $state[$digit] = ($state[$digit] + $set) % $limits[$digit];
  if($_add)
    $state = timer($_add, $state, $digit + 1);
  if($digit or $break)
    return $state;

  print strrev($state) . "\n";
  timer(1, $state);
}

timer(0, '000');
 

sloker

Новичок
Если кому интересно, я написал по своему, но с рекурсией. Но возникла проблема, появляется лишний нуль. Как избавиться?

PHP:
<?php
function timer($limit, $mas, $number) {
    $fromLimit = $limit[$number];
    for ($i = 0; $i <= $fromLimit; $i++) {
        $masCopy = $mas;
        $masCopy[$number] = $i;
        //echo "number = $number, ";
        //echo "i = $i, ";
        //echo "fromLimit = $fromLimit\n";
        if ($number >= 0) {
            timer($limit, $masCopy, $number - 1);
        } else {
            echo implode(", ", $masCopy)."\n";
            return;
        }
    }
}
timer(array(2, 1, 3), array(0, 0, 0), 2);
 

sloker

Новичок
Решил, работает. Да и код небольшой.

PHP:
<?php

function timer($limit, $mas, $number) {

    $fromLimit = $limit[$number];
    for ($i = 0; $i <= $fromLimit; $i++) {
      
        $masCopy = $mas;
        $masCopy[$number] = $i;

        if ($number < count($limit) - 1) {
            timer($limit, $masCopy, $number + 1);
        } else {
            echo implode(", ", $masCopy)."\n";
        }
    }
}

timer(array(2, 1, 3), array(0, 0, 0), 0);
 
Сверху