За последние 24 часа нас посетили 17645 программистов и 1596 роботов. Сейчас ищут 1663 программиста ...

Разучился думать, писал долго

Тема в разделе "Решения, алгоритмы", создана пользователем sylex, 25 дек 2008.

  1. sylex

    sylex Активный пользователь

    С нами с:
    9 ноя 2008
    Сообщения:
    625
    Симпатии:
    0
    Адрес:
    Омск
    Вроде простой алгоритм, который раньше бы написал за 20 минут, сейчас башка тупит от большого кол-ва проектов, предновогодней загрузки...

    Задача: Вывести сокращенную последовательность чисел. То есть везде где это можно заменить, к примеру "1,2,3,4" на "1-4".

    Массив $aFloors: ключи - пример исходных данных, значение - то, что должно получиться...

    Алгоритм:

    PHP:
    1. <?php
    2.  
    3. $aFloors = array(
    4.     '9,7,6,5,4,2,1' => '1,2,4-7,9',
    5.     '9,8,7,5,4,3,2,1' => '1-5,7-9',
    6.     '7,6,5,8,4,3,2' => '2-8',
    7.     '5,6,9,4,3,2' => '2-6,9',
    8.     '1,9,7,5' => '1,5,7,9',
    9.     '9,8,6,4,2,1' => '1,2,4,6,8,9',
    10.     '9,8,6,4,7,2,1' => '1,2,4,6-9',
    11.     '8' => '8',
    12.     '2,7,8,9' => '2,7-9',
    13.     '2,6,8,9' => '2,6,8,9'
    14. );
    15.  
    16. ?>
    17. <style type="text/css">
    18. .v TD {
    19.   font: 12px Arial;
    20.   padding: 2px 10px;
    21. }
    22. </style>
    23. <table class="v">
    24. <?php
    25. foreach ($aFloors as $key => $val) {
    26.     $res = GetFloors($key);
    27.     echo <<<EOF
    28.         <tr>
    29.         <td>{$key}</td><td>{$val}</td><td>{$res}</td>
    30.         </tr>
    31. EOF;
    32. }
    33.  
    34. function GetFloors($s)
    35. {
    36.     // разбираем по запятой
    37.     $m = explode(',', (string)$s);
    38.     if ( sizeof($m) == 1 ) return $m[0];
    39.     // сортируем
    40.     sort($m);
    41.     $count = sizeof($m);
    42.     $s = '';
    43.     $i = 0;
    44.     while($i<$count) {
    45.         $z = $m[$i]; // начальное значение
    46.         $p_end = $i; // конечное значение
    47.        
    48.         // поиск максимальной последовательности
    49.         for($j=$i+1;$j<=$count;$j++) {
    50.             $z++; // увеличиваем начальное значение
    51.             if ( $j == $count || $m[$j] != $z ) { // если это последний элемент или проверяемое не равно начальному значению
    52.                 $p_end = $j-1; // записываем конечный индекс найденной последовательности
    53.                 break; // выходим из поиска
    54.             }
    55.         }
    56.         // $i - индекс начального значения последовательности, $p_end - индекс конечного значения последовательности
    57.        
    58.         if ( $p_end-$i>1 ) {
    59.             // если разница м/у индексами последовательности > 1
    60.             $s .= $m[$i] . '-' . $m[$p_end];
    61.         } elseif ( $p_end - $i == 1 ) {
    62.             // если разница = 1
    63.             $s .= $m[$i] . ',' . $m[$p_end];
    64.         } else {
    65.             // если это последний элемент
    66.             $s .= $m[$p_end];
    67.         }
    68.        
    69.         // если это не последний элемент, ставим запятую
    70.         if ( $p_end+1 != $count ) $s .= ',';
    71.         // начальное значение = следующее за конечным (+1)
    72.         $i = $p_end + 1;
    73.     }
    74.     return $s;
    75. }
    76. ?>
    77. </table>
    Кто видит как можно сделать проще? :)
     
  2. Полезное дело. Только выкини из кода этот дуракический html.
     
  3. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    PHP:
    1. <?php
    2. $aFloors = array(
    3.     '9,7,6,5,4,2,1' => '1,2,4-7,9',
    4.     '9,8,7,5,4,3,2,1' => '1-5,7-9',
    5.     '7,6,5,8,4,3,2' => '2-8',
    6.     '5,6,9,4,3,2' => '2-6,9',
    7.     '1,9,7,5' => '1,5,7,9',
    8.     '9,8,6,4,2,1' => '1,2,4,6,8,9',
    9.     '9,8,6,4,7,2,1' => '1,2,4,6-9',
    10.     '8' => '8',
    11.     '2,7,8,9' => '2,7-9',
    12.     '2,6,8,9' => '2,6,8,9'
    13. );
    14.  
    15. $result = array();
    16.  
    17. foreach ($aFloors as $k => $null) {
    18.     $values = explode(',', $k);
    19.     sort($values);
    20.  
    21.     $pv = max($values);
    22.     $j = 0;
    23.  
    24.     foreach ($values as $v) {
    25.         if ($v - $pv > 1) {
    26.             $j++;
    27.         }
    28.  
    29.         $result[$k][$j][] = $v;
    30.         $pv = $v;
    31.     }
    32. }
    33.  
    34. print_r($result);
    35.  
    Первое что пришло в голову.
     
  4. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    Хорошая штука хоть мозг размять :)

    Заодно учет пустых строк и повторяющихся чисел

    PHP:
    1. <?php
    2.  
    3. header('Content-type: text/plain; charset=utf-8');
    4.  
    5. $aFloors = array(
    6.     '9,7,6,5,4,2,1' => '1,2,4-7,9',
    7.     '9,8,7,5,4,3,2,1' => '1-5,7-9',
    8.     '7,6,5,8,4,3,2' => '2-8',
    9.     '5,6,9,4,3,2' => '2-6,9',
    10.     '1,9,7,5' => '1,5,7,9',
    11.     '9,8,6,4,2,1' => '1,2,4,6,8,9',
    12.     '9,8,6,4,7,2,1' => '1,2,4,6-9',
    13.     '8' => '8',
    14.     '2,7,8,9' => '2,7-9',
    15.     '2,6,8,9' => '2,6,8,9'
    16. );
    17.  
    18.  
    19. $array = array_keys($aFloors);
    20.  
    21. foreach ($array as $a)
    22.     echo $a.' => '.get($a)."\n";
    23.  
    24.  
    25. function get($str) {
    26.     $values = explode(',', $str);
    27.     if (!isset($values[0]))
    28.         return '';
    29.     sort($values);
    30.  
    31.     $str = $values[0];
    32.     for ($i = 1, $s = 0; isset($values[$i]); $i++) {
    33.         if ($values[$i] - $values[$i-1] > 1) {
    34.             if ($s !== false)
    35.                 $str .= get_interval($values[$s], $values[$i-1]);
    36.             $s = false;
    37.             $str .= ','.$values[$i];
    38.         }
    39.         else {
    40.             if ($s === false)
    41.                 $s = $i-1;
    42.         }
    43.     }
    44.     if ($s !== false)
    45.         $str .= get_interval($values[$s], $values[$i-1]);
    46.  
    47.     return $str;
    48. }
    49.  
    50. function get_interval($a, $b) {
    51.     if ($b - $a > 1)
    52.         return '-'.$b;
    53.     elseif ($b == $a)
    54.         return '';
    55.     else
    56.         return ','.$b;
    57. }
    58.  
    59. ?>
     
  5. sylex

    sylex Активный пользователь

    С нами с:
    9 ноя 2008
    Сообщения:
    625
    Симпатии:
    0
    Адрес:
    Омск
    интересные решения:)
     
  6. sylex

    sylex Активный пользователь

    С нами с:
    9 ноя 2008
    Сообщения:
    625
    Симпатии:
    0
    Адрес:
    Омск
    HTML просто для показа работы этой функции :)
     
  7. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Вопрос автору - числа перечислены в строку или это массив из числел, который надо вывести в виде строки, в которой по мере возможности указаны интервалы?
     
  8. sylex

    sylex Активный пользователь

    С нами с:
    9 ноя 2008
    Сообщения:
    625
    Симпатии:
    0
    Адрес:
    Омск
    смотри топик, массив $aFloors - пример входных и выходных данных.
     
  9. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    интересна обратная задача, как в ворде.
     
  10. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    по моему, она решается намного проще.
     
  11. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    угу, тем и интересно. )