powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (PHP) Разминка для мозгов
25 сообщений из 271, страница 10 из 11
(PHP) Разминка для мозгов
    #37246912
Фотография Hett
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, ясно, все дело в разделителях у вещественных чисел. Так и виндовый 100 выдает

Код: plaintext
((( 8 / 2 )/ 2 )*(( 2 , 7 + 1 , 3 )+( 6 / 3 )-( 16 / 8 )+(( 9 / 3 )+( 2 * 3 *( 5 - 4 )))))+ 6 +((( 16 / 8 )/ 2 )*( 10 +( 3 / 1 )-( 4 / 2 )+(( 8 / 2 )+( 7 * 8 *( 3 - 2 )))))- 3 
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37247135
an0nym
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
r u,

как-то писал для польской нотации 8779246 - идея та же?
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37247201
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an0nym,

только тут строка как вы видите в другом формате) соответсвенно проблемы её разбора и обработки несколько отличаются.
но в целом можно и так

например на регекспах, понятно что тормознее, зато кода в разы меньше)
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37248148
an0nym
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
r u,

на регэкспах имхо очень трудно будет обработать неограниченную вложенность скобок.
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37251388
Vaytl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
r uДана строка:
Код: plaintext
1.
$s = '(((8/2)/2)*((2.7+1.3)+(6/3)-(16/8)+((9/3)+(2*3*(5-4)))))+6+(((16/8)/2)*(10+(3/1)-(4/2)+((8/2)+(7*8*(3-2)))))-3'; //=100
необходимо написать код который вычислит её (те калькулятор)

* Уточнения и ограничения:
- не использовать eval()
- числа в строке: десятичные int или float
- арифметические операции: + - * /
- исходить что входная строка корректна, те содержит только парные скобки и корректную вложенность(валидность входного выражения проверять ненужно)
- проверить правильность вычисления можно в поиске Гугла, там встроенный калькулятор

Вот, накидал регулярками
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
$calc = '(((8/2)/2)*((2.7+1.3)+(6/3)-(16/8)+((9/3)+(2*3*(5-4)))))+6+(((16/8)/2)*(10+(3/1)-(4/2)+((8/2)+(7*8*(3-2)))))-3'; //=100

 function  calc($matches)  
  { 
   preg_match_all ("'([*/])'",$matches[ 1 ],$array1);
   preg_match_all ("'([+-])'",$matches[ 1 ],$array2);
 if ( preg_match ("'[*/]'", $matches[ 1 ]))  {
    for ($i =  0 ; $i <  count ($array1[ 1 ]); $i++) {
	   $matches[ 1 ] =  preg_replace_callback ("'([\d.]+)([*/])([\d.]+)'", create_function (
	   '$matches','if($matches[2] == "*") return  $matches[1] * $matches[3]; else return  $matches[1] / $matches[3];'),$matches[ 1 ]);
  }
   }
 if ( preg_match ("'[+-]'", $matches[ 1 ]))  {
    for ($i =  0 ; $i <  count ($array2[ 1 ]); $i++) {
	   $matches[ 1 ] =  preg_replace_callback ("'([\d.]+)([+-])([\d.]+)'", create_function (
	   '$matches',' if($matches[2] == "-") return  $matches[1] - $matches[3]; else return  $matches[1] + $matches[3];'),$matches[ 1 ], 1 );
 }
  }
      return  $matches[ 1 ];
  } 
   do 
  {
 echo  $calc.'<br>';
	$calc =  preg_replace_callback ("'\(([^()]+)\)'","calc", $calc);  
  }
 while  ( preg_match ("'[\(\)]'", $calc));

 echo  $calc.'<br>';
 echo   preg_replace_callback ("'(.*)'","calc", $calc);
PS. Хорошая вышла разминка для мозгов ))
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37252133
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vaytl,

да, регулярками у меня тоже подобный подход, только код немного другой)
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37253540
Vaytl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
r u,
Хотелось бы увидеть ваш код, для сравнения…(если можно)
Немного поправил свой код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
$calc = '(((8/2)/2)*((2.7+1.3)+(6/3)-(16/8)+((9/3)+(2*3*(5-4)))))+6+(((16/8)/2)*(10+(3/1)-(4/2)+((8/2)+(7*8*(3-2)))))-3'; //=100

 function  calc($matches)  {  
 while  ( preg_match ("'[/*]'", $matches[ 1 ])) {
	   $matches[ 1 ] =  preg_replace_callback ("'([\d.]+)([*/]+)([\d.]+)'", create_function ('$matches',
	   'if(($matches[2]) == "*") return  $matches[1] * $matches[3]; else return  $matches[1] / $matches[3];'),$matches[ 1 ]);
       }
 while  ( preg_match ("'[+-]'", $matches[ 1 ])) {
	   $matches[ 1 ] =  preg_replace_callback ("'([\d.]+)([+-]+)([\d.]+)'", create_function ('$matches',
	   'if(($matches[2]) == "-") return  $matches[1] - $matches[3]; else return  $matches[1] + $matches[3];'),$matches[ 1 ], 1 );
       }
      return  $matches[ 1 ];
 } 
   do 
  {
	$calc =  preg_replace_callback ("'\(([^()]+)\)'","calc", $calc);  
 }
 while  ( preg_match ("'[()]'", $calc));

 echo   preg_replace_callback ("'(.*)'","calc", $calc);
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37253592
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vaytl,

мой вариант через регулярки

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
 define ('D',    '\d+(?:\.\d+)?');
 define ('G_MDB','/(\('.D.'[-+*\/]'.D.'\)|'.D. '[*\/]'.D.')/');
 define ('G_AS', '/'.D.'[-+]'.D.'/');
 define ('G_D',  '/('.D.')([-+*\/])('.D.')/');
//
 function  opers($matches) {
	 preg_match (G_D, $matches[ 0 ], $m);
	 if  ($m[ 2 ] == '*')  return  $m[ 1 ] * $m[ 3 ];
	 if  ($m[ 2 ] == '/')  return  $m[ 1 ] / $m[ 3 ];
	 if  ($m[ 2 ] == '+')  return  $m[ 1 ] + $m[ 3 ];
	 if  ($m[ 2 ] == '-')  return  $m[ 1 ] - $m[ 3 ];
}
//
$s = '(((8/2)/(2))*((2.7+1.3)+(6/3)-(16/8)+((9/3)+(2*3*(5-4)))))+6+(((16/8)/2)*(10+(3/1)-(4/2)+((8/2)+(7*8*(3-2)))))-3';
 while  ( preg_match ('/[-+*\/]/', $s)) {
	$s =  preg_replace ('/\(('.D.')\)/', '\1', $s);
	$s =  preg_replace_callback (G_MDB,'opers', $s);
	$s =  preg_replace_callback (G_AS, 'opers', $s);
}
 echo  $s;
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37253614
Vaytl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
r u,

Спасибо, очень познавательно + в 2-3 раза быстрее моего примера…
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37253620
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
имхо, у решения через регекспы есть существенный минус - скорость работы. замеры скорости не делал, но чтобы не быть голословным решил написать решение "классически" - с пом. трансляции в польскую нотацию и последующим её вычислением(выше свой вариант приводил an0nym). только я не стал решать задачу настолько широко и универсально, получилось чтото такое
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
 function  convertToPolishNotation($s) {
	$stack = $out = $items =  array ();
	 preg_match_all ('/(\d+(\.\d+)?|[-+*\/()])/', $s, $items);
	 foreach  ($items[ 0 ]  as  $c) {
		 if  ( is_numeric ($c)) $out[] = $c;
		 else  _addPnItem($stack, $out, $c);
	}
	 if  ( sizeof ($stack))
		$out =  array_merge ($out,  array_reverse ($stack));
	 return  $out;
}
//
 function  _addPnItem(&$stack, &$out, $c) {
	static $prior =  array ('*' =>  3 , '/' =>  3 , '+' =>  2 , '-' =>  2 , '(' =>  1 );
	 if  ( sizeof ($stack) ==  0  || $c == '(') {
		$stack[] = $c;
	}  elseif  ($c == ')') {
		 for  ($i =  sizeof ($stack) -  1 ; $i >=  0 ; --$i) {
			 if  ($stack[$i] == '(') {
				 array_pop ($stack);
				 break ;
			}
			 else  $out[] =  array_pop ($stack);
		}
	}  else  { // + - * /
		 for  ($i =  sizeof ($stack) -  1 ; $i >=  0 ; --$i) {
			$oper = $stack[$i];
			 if  ($prior[$oper] >= $prior[$c]) {
				$out[] = $oper;
				 unset ($stack[$i]);
			}
			 else   break ;
		}
		$stack[] = $c;
		$stack =  array_values ($stack);
	}
}
//
 function  calculatePolishNotation( Array  $s) {
	$pair =  array ();
	 foreach  ($s  as  $v) {
		 if  ( is_numeric ($v))
			$pair[] = $v;
		 else  {
			$size =  sizeof ($pair) -  2 ;
			 if  ($v == '*') $pair[$size] *=  array_pop ($pair);
			 if  ($v == '/') $pair[$size] /=  array_pop ($pair);
			 if  ($v == '+') $pair[$size] +=  array_pop ($pair);
			 if  ($v == '-') $pair[$size] -=  array_pop ($pair);
		}
	}
	 return  $pair[ 0 ];
}

//
$str = '(((8/2)/(2))*((2.7+1.3)+(6/3)-(16/8)+((9/3)+(2*3*(5-4)))))+6+(((16/8)/2)*(10+(3/1)-(4/2)+((8/2)+(7*8*(3-2)))))-3';
$str_pn = convertToPolishNotation($str);
$res = calculatePolishNotation($str_pn);
 echo  $res;

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

пытался написать алгоритм вычисления налету с одним прогоном - но неосилил))
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37253645
Vaytl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
r uимхо, у решения через регекспы есть существенный минус - скорость работы. замеры скорости не делал, но чтобы не быть голословным решил написать решение "классически" ....
Как ни странно, но ваш пример через регекспы, работает быстрее второго варианта на 50-100%...
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37253659
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VaytlКак ни странно, но ваш пример через регекспы, работает быстрее второго варианта на 50-100%...
странно))) думал будет наоборот
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37256229
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VaytlКак ни странно, но ваш пример через регекспы, работает быстрее второго варианта на 50-100%...
добился небольшого но выигрыша в скорости второго варианта )
избавился от регекспа и функции _addPnItem() (передача по ссылке тормозила, глобальные переменные тоже).
думаю можно оптимизировать и сам алгоритм, но это уже отдельная история)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
 function  convertToPolishNotation($s) {
	static $prior =  array ('*' =>  3 , '/' =>  3 , '+' =>  2 , '-' =>  2 , '(' =>  1 );
	$stack = $out = $items =  array ();
	// get operators & operands
	$d= null ;
	 for ($i= 0 ,$l= strlen ($s); $i<$l; ++$i) {
		 if  ( is_numeric ($s{$i}) || $s{$i}=='.') $d.=$s{$i};
		 else  {
			 if  ($d!= null ) {
				$items[]=$d;
				$d= null ;
			}
			$items[]=$s{$i};
		}
	}
	 if  ($d!= null )
		$items[]=$d;
	//
	 for ($i= 0 ,$m= sizeof ($items); $i<$m; ++$i) {
		 if  ( is_numeric ($items[$i]))
			$out[] = $items[$i];
		 else  { // addPn
			 if  ( sizeof ($stack) ==  0  || $items[$i] == '(') {
				$stack[] = $items[$i];
			}  elseif  ($items[$i] == ')') {
				 for  ($ii =  sizeof ($stack) -  1 ; $ii >=  0 ; --$ii) {
					 if  ($stack[$ii] == '(') {
						 array_pop ($stack);
						 break ;
					}
					 else  $out[] =  array_pop ($stack);
				}
			}  else  { // + - * /
				 for  ($ii =  sizeof ($stack)- 1 ; $ii>= 0 ; --$ii) {
					$oper = $stack[$ii];
					 if  ($prior[$oper] >= $prior[$items[$i]]) {
						$out[] = $oper;
						 unset ($stack[$ii]);
					}
					 else   break ;
				}
				$stack[] = $items[$i];
				$stack =  array_values ($stack);
			}
		}
	}
	 if  ( sizeof ($stack))
		$out =  array_merge ($out,  array_reverse ($stack));
	 return  $out;
}
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37303902
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дан массив чисел:
Код: plaintext
1.
2.
3.
4.
$a =  array (
  0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 
  0 , 1 , 2 , 3 , 4 , 5 , 6 ,   8 , 9 
);
Как видно, в массиве все числа, кроме одного, встречаются 2 раза, а одно число(7) только один раз.
необходимо найти это число всего за один проход массива.

PS всякие готовые функции array_xxxxx() и т.п. использовать нельзя
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37303918
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а в чем прикол
Код: plaintext
1.
2.
3.
$rez =  array ();
 foreach  ($arr  as  $key=>$value){
   @$rez[$value]++;
}
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37303931
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowа в чем прикол
Код: plaintext
1.
2.
3.
$rez =  array ();
 foreach  ($arr  as  $key=>$value){
   @$rez[$value]++;
}

ну вы получили еще один массив.
выведите найденный элемент ,только его ))
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37303951
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
без прохода по второму массиву?
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37304183
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowбез прохода по второму массиву?
да.
тогда уточню немного.

Дан массив чисел:
Код: plaintext
1.
2.
3.
4.
5.
$a =  array (
  0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 
  0 , 1 , 2 , 3 , 4 , 5 , 6 ,   8 , 9 
);
$n= null ;

Как видно, в массиве все числа, кроме одного, встречаются 2 раза, а одно число(7) только один раз.
необходимо найти это число, всего за один проход массива, и поместить найденное число в переменную $n .

PS всякие готовые функции array_xxxxx() и т.п. использовать нельзя
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37304817
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
r u,

$a = array(
0,1,2,3,4,5,6,7,8,9,
0,1,2,3,4,5,6, 8,9
);
$n = 0;
foreach($a as $v){
$n=$n ^ $v; //иногда исключающее или всетаки нужно
}
echo $n;
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37305166
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas,

поздравляю)
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37307630
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тоже самое задание, но....
Дан массив букаф:
Код: plaintext
1.
2.
3.
4.
$a =  array (
 'a','b','c','d','e','f','g','h','q','n', 
 'a','b','c',    'e','f','g','h','q','n',
);
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37307660
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas,

решение тоже самое. только изначально $n="\0";
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37764907
an0nym
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добейтесь появления у объекта двух свойств с одинаковым названием и разной областью видимости. :)
...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37765651
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an0nymДобейтесь появления у объекта двух свойств с одинаковым названием и разной областью видимости. :)
легко )

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
class Obj {
	private $name = 'private var';
	public function getPrivate() {
		var_dump($this->name);
	}
}
class Obj2 extends Obj {
	protected $name = 'public var';
	public function getPublic() {
		var_dump($this->name);
	}
}
echo '<pre>';
$o = new Obj2();
$o->getPrivate();
$o->getPublic();


...
Рейтинг: 0 / 0
(PHP) Разминка для мозгов
    #37765692
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Усложняем задачу:

-Добейтесь появления у объекта ТРЕХ свойств с одинаковым названием и разной областью видимости.
...
Рейтинг: 0 / 0
25 сообщений из 271, страница 10 из 11
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (PHP) Разминка для мозгов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]