2010-09-19 10 views
2

У меня нет абсолютно никакой идеи, поэтому, если кто-то может указать мне в правильном направлении, было бы весьма полезно.Рекурсивная функция

Я хочу иметь что-то вроде

<?php 
function square($num) { 
// something 
} 

name('{3}'); // have this return 9 
name('{6}'); // have this return 36 
name('{{{2}}}'); // have this return 256 
name('{9}{12}'); // have this return 81144 
name('{{5}}'); // have this return 125 
name('adscdc{4}{{3}}'); // have this return adscdc1681 
?> 

Кто-нибудь есть идеи, как это можно сделать? Заранее спасибо :) До сих пор у меня есть:

<?php 
function square($text) { 
    $parts = explode('{', $text); 
    foreach($parts as $part) { 
     $piece = explode('}', $part); 
     $text = str_replace('{' . $piece[0] . '}', pow($piece[0], 2), $text); 
    } 
    return $text; 
} 
echo square('aasd{3}'); 
?> 
+0

Это похоже домашнее задание. Что у вас есть? –

+0

Является ли это домашней проблемой? –

+0

это домашнее задание? – kennytm

ответ

0

настоящей Краткой {} скобка и для каждого кронштейна получить десятичный в ней и власти к числу кронштейна вложен, выход был concated в строку вместо разобранной скобки без любой разделительный характер.

2

Возможно, вам придется разбирать строку. Продолжайте читать символы, пока не достигнете открытой фигурной скобки, а затем на каждой открытой скобке прирастите счетчик. Когда вы добираетесь до номера, поднимите его на мощность счетчика. Затем декремент для каждой закрывающей фигурной скобки, и если фигурные скобки не совпадают, генерирует исключение.

+0

Возможно, используя str_split, а затем проведите через них синтаксический анализ? – Tech163

+0

@ Tech163 Просто перебирайте символы строки. – Skilldrick

+0

+1 для консультации с regex hyginx – SingleNegationElimination

0

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

name('{{9}{{{{{1}'); 
name('{abbc}'); 
name('{}'); 
+0

Согласование скобок обрабатывается описанным алгоритмом - приращение на открытии, уменьшение на близком расстоянии и проверка того, что он возвращается к нулю до нового приращения. Вы правы в проверке таких вещей, как нечисловые символы в фигурных скобках. Я думаю, что в том числе нечисловые символы на входе - это немного глупое требование. – Skilldrick

+1

Он также обрабатывается с помощью регулярного выражения. Строка всегда действительна, непревзойденные фигурные скобки становятся буквальными символами. Если вам нужна строгая проверка, проверьте полученную строку и выделите исключение, если оно содержит какие-либо символы '' '' '' '' '' '' '' '' '' ''. –

1

Выглядит просто. Когда вы обнаруживаете мотив как число внутри фигурных скобок, его следует заменить квадратом числа. Если замена не завершена, вы закончите. Если какая-то замена выполняется, вы делаете это снова (потому что то, что было просто заменено, теперь может быть внутри фигурных скобок) и так далее.

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

Ниже приведен фрагмент кода, который поможет вам понять детали (не полный ответ, но не далеко). Цель упражнений состоит в том, чтобы помочь вам понять параметры preg_replace().

<?php 
$count = 0; 
echo preg_replace('/[{](\d+)[}]/e', '$1*$1', '{{{2}}}', -1, $count); 
echo "\n"; 
echo "$count replacement done\n"; 
?> 

Как и другие предложили полные решения, здесь его шахту:

<?php 

function square($str){ 
    $count = 0; 
    do { 
     $str = preg_replace('/[{](\d+)[}]/e', '$1*$1', $str, -1, $count); 
    } while ($count); 
    return $str; 
} 

echo square('{3}')."\n"; // have this return 9 
echo square('{6}')."\n"; // have this return 36 
echo square('{{{2}}}')."\n"; // have this return 256 
echo square('{9}{12}')."\n"; // have this return 81144 
echo square('{{5}}')."\n"; // have this return 125 
echo square('adscdc{4}{{3}}')."\n"; // have this return adscdc1681 

?> 

Если ваш озабочены проблемами совместимости (потому что закаленные установка PHP может запретить использование/е) просто использовать preg_replace_callback вместо preg_replace как ниже (используйте анонимную функцию, доступную с PHP 5.2.3, для более старой версии php вы можете использовать create_function()).

function square($str){ 
    $count = 0; 
    do { 
     $str = preg_replace_callback('/[{](\d+)[}]/', 
        function($m) {return $m[1]*$m[1];}, 
        $str, -1, $count); 
    } while ($count); 
    return $str; 
} 

Для любопытных читателей, как кто-то предложил версию питона, ниже можно Perl эквивалент:

#!/usr/bin/perl 

my @tests = ('{3}','{6}','{{{2}}}','{9}{12}','{{5}}', 'adscdc{4}{{3}}'); 

sub square { 
    my $str = pop; 
    while ($str =~ s/[{](\d+)[}]/$1*$1/e) {}; 
    return $str; 
} 

for my $str (@tests){ 
    print "$str --> ".square($str)."\n" ; 
} 

Там механизмы безопасности в Perl, чтобы избежать инъекции из-за дурных данных, вводимых пользователем, отличных от слепо отвергать все оценки. Для желающих вы можете посмотреть here.

И две другие более короткие версии питона, рекурсивный:

import re 
test = ['5','{3}','{6}','{{{2}}}','{9}{12}','adscdc{4}{{3}}'] 

def square(txt): 
    txt2 = re.sub('{(\d+)}',lambda m: str(int(m.group(1)) ** 2) , txt) 
    if txt2 == txt: 
     return txt 
    return square(txt2) 

for x in test: 
    print("%s --> %s" % (x, square(x))) 

и не рекурсивной

import re 
test = ['5','{3}','{6}','{{{2}}}','{9}{12}','adscdc{4}{{3}}'] 

def square(txt): 
    oldtxt = None 
    while oldtxt != txt: 
     oldtxt = txt 
     txt = re.sub('{(\d+)}',lambda m: str(int(m.group(1)) ** 2) , oldtxt) 
    return txt 

for x in test: 
    print("%s --> %s" % (x, square(x))) 
+0

@stereofrog: вы правы, группировка - это просто привычка читаемости (что-то предлагает Дэмиен Конвей в «Perl Best Practices», который пойман со мной). – kriss

+0

здесь является модификатором '/ e' (' PREG_REPLACE_EVAL'). Это рассматривается как риск для безопасности, поскольку он работает как 'eval'. Моды вроде Suhosin disable '/ e', поэтому он не будет работать везде ... –

+0

@no: да, но поскольку этот вопрос не помечен * hardened-php * или * Suhosin *, я считаю, что ваш комментарий не имеет значения.Также это конкретное использование/e не является проблемой безопасности здесь. По крайней мере, вы должны объяснить в своем ответе, почему вы не принимаете прямой путь, но некоторое обходное решение (а не прямое: используйте preg_replace_callback вместо/e). – kriss

3

Я думаю, что {{5}} должна быть 625, верно?

Во всяком случае, попробовать что-то вроде этого:

<?php 

    function name ($str) { 
    while (1) { 
     preg_match('/{(\d+)}/', $str, $matches); 
     if (count($matches)<2) return $str; 
     $str=str_replace($matches[0], $matches[1]*$matches[1], $str); 
    } 
    } 

    echo "\n<pre>\n". 
     name('{3}'). // have this return 9 
     "\n". 
     name('{6}'). // have this return 36 
     "\n". 
     name('{{{2}}}'). // have this return 256 
     "\n". 
     name('{9}{12}'). // have this return 81144 
     "\n". 
     name('{{5}}'). // have this return 625 
     "\n". 
     name('adscdc{4}{{3}}'). // have this return adscdc1681 
     "\n</pre>\n"; 

?> 

... ход, который дал мне эти результаты:

 
9 
36 
256 
81144 
625 
adscdc1681 
+0

Спасибо нет. Прекрасно работает! – Tech163

+0

не проблема :) Я подумал об этом и немного отредактировал его, чтобы функция возвращала значения, а не эхом их ... теперь я думаю немного более прямолинейно. –

+0

Вы также можете сделать это 'do',' while' loop, если вам не нравится 'while (1)' - http://codepad.viper-7.com/w7Q77N ------ Хотя в В этом случае я не уверен, что это все понятно. –

1

Я думал, эта проблема интересна. Но я уже вижу хорошие ответы на PHP, так что просто для тренировки самостоятельно я реализовал решение на Python. Если вы заинтересованы, вы можете посмотреть здесь:

>>> import re 
>>> test = [('5','5'),('{3}','9'),('{6}','36'),('{{{2}}}','256'),('{9}{12}','81144'),('adscdc{4}{{3}}','adscdc1681')] 
>>> def eval(txt): 
... replace = lambda t: re.sub('{(\d+)}',lambda match: str(int(match.group(1)) * int(match.group(1))),t) 
... while(re.search('[{}]',txt) != None): 
...  txt = replace(txt) 
... return txt 
... 
>>> for t in test: 
... print (t[0],t[1],eval(t[0]) == t[1]) 
... 
('5', '5', True) 
('{3}', '9', True) 
('{6}', '36', True) 
('{{{2}}}', '256', True) 
('{9}{12}', '81144', True) 
('adscdc{4}{{3}}', 'adscdc1681', True) 

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

(Это сообщение не следует рассматривать как ответ на публикуемую проблемы, потому что уже есть достаточно хорошие ответы. Я просто разделить его для заинтересованных глаз.)

Смежные вопросы