2013-03-06 4 views
0

Итак, я довольно новичок в Mathematica, и я стараюсь научиться решать проблемы функциональным способом. Проблема, которую я решала, заключалась в том, чтобы указать, как я мог бы суммировать элементы из списка (с повторениями), поэтому сумма равна leq до некоторого значения. Код ниже решает это просто отлично.Вариант резки в Mathematica

i = {7.25, 7.75, 15, 19, 22}; 
m = 22; 
getSum[l_List, n_List] := Total[Thread[{l, n}] /. {x_, y_} -> x y]; 
t = Prepend[Map[Range[0, Floor[m/#]] &, i], List]; 
Outer @@ %; 
Flatten[%, ArrayDepth[%] - 2]; 
Map[{#, getSum[i, #]} &, %]; 
DeleteCases[%, {_, x_} /; x > m || x == 0]; 
TableForm[Flatten /@ SortBy[%, Last], 0, 
TableHeadings -> {None, Append[i, "Total"]}] 

Однако код проверка много случаев, ненужных, которые могли бы быть проблемой, если т выше список больше. Мой вопрос - это просто то, что было бы самым математическим способом решения этой проблемы, как эффективности, так и элегантности кода.

+3

Не имеет смысла перекрестные ссылки здесь и на Mathematica.StackExchange - в основном те же люди в обоих местах, только большинство из нас переключилось на этот. –

ответ

1

Один простой, хотя и не оптимальный путь:

sol = Reduce[Dot[i, {a, b, c, d, e}] <= m, {a, b, c, d, e}, Integers]; 

сначала попробовать с меньшим i, скажем i = {7.25, 7.75}, чтобы получить чувство о, можно ли использовать это.

Вы можете улучшить скорость, обеспечивая верхние пределы для коэффициентов, как в

sol = Reduce[And @@ {Dot[i, {a, b, c, d, e}] <= m, 
        Sequence @@ Thread[{a, b, c, d, e} <= Quotient[m, i]]}, 
     {a, b, c, d, e}, Integers] 
+1

Я бы поднял планку, но ваш общий репутация теперь выглядит намного лучше, чем при добавлении 10. –

+0

@HighPerformanceMark Я должен согласиться, я возьму духовную поддержку. –

+0

Очень аккуратный код! Тем не менее, это кажется невероятно медленным по сравнению с моим решением, которое я хотел улучшить! – maestron

0

Как насчет

recurr[numbers_, boundary_] := 

    Reap[memoryRecurr[0, {}, numbers, boundary]][[2, 1]]; 

memoryRecurr[_, _, {}, _] := Null; 

memoryRecurr[sum_, numbers_, restNumbers_, diff_] := 
    (
    Block[ 
    {presentNumber = First[restNumbers], restRest = Rest[restNumbers]} 
    , 
    If[ 
     presentNumber <= diff 
     , 
     Block[{ 
     newNumbers = Append[numbers, presentNumber], 
     newSum = sum + presentNumber 
     }, 
     Sow[{newNumbers, newSum}]; 

     memoryRecurr[ 
     newSum, 
     newNumbers, 
     restRest, 
     diff - presentNumber 
     ]; 
     ] 
     ]; 
    memoryRecurr[sum, numbers, restRest, diff] 
    ]; 

    ); 

Так что

recurr[{1, 2, 3, 4, 5}, 7] 

->

{{{1}, 1}, {{1, 2}, 3}, {{1, 2, 3}, 6}, {{1, 2, 4}, 7}, {{1, 3}, 
    4}, {{1, 4}, 5}, {{1, 5}, 6}, {{2}, 2}, {{2, 3}, 5}, {{2, 4}, 
    6}, {{2, 5}, 7}, {{3}, 3}, {{3, 4}, 7}, {{4}, 4}, {{5}, 5}}