Как получить наиболее близкие повторяющиеся значения в массиве к целевому значению, используя Javascript?

1

// Shorthand for $( document ).ready()
$(function() {
  var SwitchesByNumberOfPorts = [48,24];
  var Target = 115;
  var Target_Copy = Target;
  var needSwitches = [];

  SwitchesByNumberOfPorts.forEach(function(ports) {
    while(Target_Copy >= ports) {
      Target_Copy -= ports;
      needSwitches.push(ports);
    }
  });

  var portsCalculated = needSwitches.reduce((a, b) => a + b, 0);

  if (portsCalculated<Target){
    var RemainingTarget = Target - portsCalculated;
    var AdditionalPorts = SwitchesByNumberOfPorts.reduce(function (prev, curr) {
    return (Math.abs(curr - RemainingTarget) < Math.abs(prev - RemainingTarget) ? curr : prev);
    });
    needSwitches.push(AdditionalPorts)
  }
	$("#result").html(needSwitches.join(", "));
	//console.log(needSwitches);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result">Loading...</div>

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

Доступны сетевые коммутаторы: 24 и 48 портов на единицу.

Например, если у клиента в настоящее время имеется 115 портов, наиболее оптимальным решением будет два коммутатора из 48 портов и 1 коммутатор из 24 портов, оставляющий 5 доступных портов.

Я ищу алгоритмы или функции в JavaScript, которые позволят мне добавить массив значений [24,48] и получить ближайший результат к цели 115.

var SwitchesByNumberOfPorts = [24,48]
var Target = 115
getClosestArrayValues(SwitchesByNumberOfPorts , Target)

// Expected Result  [48,48,24] #120 ports
Теги:
arrays
algorithm

2 ответа

0
Лучший ответ
  1. сортировать от высокого до низкого

sorted = vals.sort((a,b) => b>a)

  1. Для каждого элемента вычитайте из целевого значения, пока вы больше не сможете, и отслеживайте

sorted.forEach(v => { while(target_copy >= v) { target_copy -= v needs.push(v) } })

  1. тем не менее, это оставит последнюю покупку необходимой, поэтому в конце проверьте, нужно ли снова покупать самую маленькую

    if (target_copy> 0) {needs.push (отсортировано [sorted.length -1])}

Здесь консоль js показывает ее в действии:

function seek (set, target) {
 let needs = []
 let sorted = set.sort((a,b) => b>a)
 sorted.forEach(v => {
   while(target >= v) {
     target -= v
     needs.push(v)
   }
 })
 if(target > 0) { needs.push(sorted[sorted.length - 1]) }
 return needs
}
undefined
seek([48,24],115)
(3) [48, 48, 24]
  • 0
    Ваше решение быстрое и «работает», но не дает оптимальных результатов. Например, seek([30, 20, 15], 35) оценивается как [30, 15] тогда как оптимальным решением будет [20, 15] .
  • 0
    Благодаря le_m в моем случае мне нужно учесть самый высокий коммутатор портов и решение, предложенное Роберто Томасом, достаточно хорошо охватило эту причину, поэтому он сначала сортирует по самым высоким значениям. Спасибо за ваш вклад.
2

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

{0:[]}

Затем для каждого значения на входе повторяйте значения в сите (включая те, которые вы только что добавили на этом шаге), и добавьте к ним значение до тех пор, пока вы не достигнете или не пройдете цель. В этом примере мы начинаем с 48:

{0:[], 48:[48], 96:[48,48], 144:[48,48,48]}

Сделайте то же самое для следующего значения 24:

{0:[], 24:[24], 48:[48], 72:[48,24], 96:[48,48], 120:[48,48,24], 144:[48,48,48]}

Когда новое значение, которое вы создаете, например 24 + 24 = 48, уже присутствует, не заменяйте его, чтобы использовалось наименьшее количество значений, т.е. Вместо 24 + 24, 48 + 24 вместо 24 + 24 +24 и т.д.

Когда вы просмотрите все значения, возьмите первый элемент в сите, который равен или больше цели. В этом примере:

120:[48,48,24]

Для примера ввода [30, 20, 15] и целевого значения 35 это будет:

{0:[]}
{0:[], 30:[30], 60:[30,30]}
{0:[], 20:[20], 30:[30], 40:[20,20], 60:[30,30]}
{0:[], 15:[15], 20:[20], 30:[30], 35:[20,15], 40:[20,20], 60:[30,30]}

И результат:

35:[20,15]

ПРИМЕЧАНИЕ. Если вы предпочитаете использовать значения, отличные от высоко-низко, просто сортируйте значения в порядке предпочтения перед созданием сита; например, с использованием [20, 15, 30] приведет к 65: [20,15,15,15] вместо 65: [30,20,15].

  • 1
    Отличное решение!
  • 0
    @ robertotomás Когда проблема похожа на обмен монет, всегда есть вариант сита, особенно если значения небольшие.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню