Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Наиболее близкое число


Автор: MoLeX 16.10.2011, 18:44
Добрый вечер.

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

Например, у нас массив чисел (ключ это и есть число)
Код

$d[30] = '';
$d[1] = '';
$d[18] = '';
$d[9] = '';
$d[25] = '';


Допустим загадаем число 16, соответственно максимально близкое будет - 18.

И еще один пример:
Код

$d[1] = '';
$d[10] = '';
$d[9] = '';

В этом случае максимально близким числом будет 10.

Как это реализовать?

Автор: patap 16.10.2011, 19:20
Код

$d[1] = '';
$d[10] = '';
$d[9] = '';
    
    $number = 16;
    $result = NULL;

    foreach ($d as $key => $val)
    {
        $diff = abs($key - $number);
        if ( ! $result)
        {
            $result['key'] = $key;
            $result['diff'] = $diff;
            continue;
        }

        if ($result['diff'] > $diff)
        {
            $result['key'] = $key;
            $result['diff'] = $diff;
        }
        
    }

    echo '<pre>';
    print_r($result);

Автор: Absinthe 16.10.2011, 19:32
Код

<?php

$d[30] = '';
$d[1] = '';
$d[18] = '';
$d[9] = '';
$d[25] = '';

$target = 16;

$unsorted = array_map(function($key) use ($target) { return $key - $target;}, array_keys($d));
usort($unsorted, function($a, $b) {return abs($a) - abs($b);});
echo $unsorted[0] + $target;

Автор: Evghenusi 16.10.2011, 23:26
решил тоже поучаствовать в теме, не знаю мой вариант ГК или нет, решать вам.

Код
<?php
$n=16;

$d[30] = '';
$d[1] = '';
$d[18] = '';
$d[9] = '';
$d[25] = '';
$d[10] = '';

$a = $d;

if(!isset($a[$n]))
$a[$n] = '';

ksort($a);
$k = array_keys($a);
$f = array_search($n, $k);
$prev = $n - $k[$f-1];
$next = $k[$f+1] - $n;
$result = $prev < $next ? $k[$f-1] : $k[$f+1];

echo "Наиболее близкое число \$d[$result]";
?>

Автор: Shogun 17.10.2011, 11:36
Evghenusi, +1

Автор: Evghenusi 17.10.2011, 12:58
предыдущий вариант с ошибкой, а новый со страшной проверкой  smile 

Код
<?php
$d[30] = '';
$d[1] = '';
$d[18] = '';
$d[9] = '';
$d[25] = '';
$d[10] = '';

$a[1] = '';
$a[10] = '';
$a[9] = '';

function closest_number($arr, $number)
{
$arr = array_keys($arr);
if(!in_array($number, $arr))
$arr[] = $number;
sort($arr);
$f = array_search($number, $arr);

if(isset($arr[$f-1]) && isset($arr[$f+1]))
{
    if($number - $arr[$f-1] < $arr[$f+1] - $number)
    $result = $arr[$f-1];
    else
    $result = $arr[$f+1];
}
else 
{
    if(isset($arr[$f-1]))
    $result = $arr[$f-1];
    elseif(isset($arr[$f+1]))
    $result = $arr[$f+1];
    else 
    $result = 'увы';
}
return 'Наиболее близкое число '.$result;
}

echo closest_number($d, 16),"\n";
echo closest_number($a, 16);
?>

Автор: Muerto 17.10.2011, 14:27
Нужно отсортировать затем от нашего числа посмотреть влево и вправо, и выбрать.

Автор: Evghenusi 17.10.2011, 16:10
Цитата(Muerto @  17.10.2011,  14:27 Найти цитируемый пост)
Нужно отсортировать затем от нашего числа посмотреть влево и вправо, и выбрать.
 smile 

Автор: Shogun 17.10.2011, 21:09
Код

$n = 16;

$ar[30] = '';
$ar[1] = '';
$ar[18] = '';
$ar[9] = '';
$ar[25] = '';
$ar[10] = '';

if (in_array($n, array_keys($ar))) { echo 'Key: ', $n; }

$ar[$n] = '';

ksort($ar);

$keys = array_keys($ar);

$i = array_search($n, $keys);

$key = (abs(abs($keys[$i-1]) - $n) < abs(abs($keys[$i+1]) - $n)) ? $keys[$i-1] : $keys[$i+1];

echo 'Key: ', $key;

Автор: Evghenusi 17.10.2011, 22:18
Shogun, спасибо за пример, хотя ждал его от Muerto.

Shogun, не знаю что оптимальнее (по скорости, потреблении памяти) ksort или sort, но если равнозначно, да ещё и присутствуют функции in_array и array_keys то почему бы не sort?, и почему не воспользоваться ф. array_keys один раз?  smile 

Зачем выводить сообщение о нахождении в массиве элемента с ключом равным значению искомого числа, а после опустошать ($ar[$n] = '') его значение тоже не совсем понятно.

За пример проверки "получаемых" данных отдельное спасибо, думал abs не понадобится (хотя видел в примерах от patap и Absinthe), а вы доказали что необходим.

Автор: MoLeX 18.10.2011, 06:05
Всем спасибо. Больше всех понравился пример Shogun. Но его немного модернизировал
Код

$n = 10;
$ar[30] = '';
$ar[1] = '';
$ar[18] = '';
$ar[9] = '';
$ar[25] = '';
$ar[11] = '';

if( isset($ar[$n]) )
    $key = $n;    
else
{
    $ar[$n] = '';
    ksort($ar);
    $keys = array_keys($ar);
    $i = array_search($n, $keys);
    $key = (abs(abs($keys[$i-1]) - $n) < abs(abs($keys[$i+1]) - $n)) ? $keys[$i-1] : $keys[$i+1];
}

echo 'Key: ', $key;

Автор: Shogun 18.10.2011, 10:23
MoLeX, isset тут не совсем правильно используется, тогда уж так:

Код

$n = 10;
$ar[30] = '';
$ar[1] = '';
$ar[18] = '';
$ar[9] = '';
$ar[25] = '';
$ar[11] = '';

$key = $n;

if (!array_key_exists($n, $ar))
  {
    $ar[$n] = '';
    ksort($ar);
    $keys = array_keys($ar);
    $i = array_search($n, $keys);
    $key = (abs(abs($keys[$i-1]) - $n) < abs(abs($keys[$i+1]) - $n)) ? $keys[$i-1] : $keys[$i+1];
  }

echo 'Key: ', $key;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)