Adding the last two elements of a list - wolfram-mathematica

In Mathematica, what is the cleanest way of taking a list
{r1, r2, r3, ..., rn, a, b}
and returning
{r1, r2, r3, ..., rn, a + b}
or more generally
{r1, r2, r3, ..., rn, f[a, b]}
for some function f?

lst = {a[1], a[2], a[3], a[4], a[5], a[6], a[7], a, b};
lst /. {a___, b_, c_} -> {a, f[b, c]}
==> {a[1], a[2], a[3], a[4], a[5], a[6], a[7], f[a, b]}
or (ugly):
Append[Take[lst, {1, -3}], f ## lst[[{-2, -1}]]]

I'd use rules if performance is not a big issue (lists are not packed etc):
lst = {a, b, c, d, e}
In[13]:= Replace[lst, {left__, ntl_, l_} :> {left, f[ntl, l]}, {0}]
Out[13]= {a, b, c, f[d, e]}

If I hadn't second guessed Simon I would have been first to answer. Nuts. Anyway, here is my late-to-the-party reply.
combineLast =
Module[{x = #},
x[[-2]] = #2 ## x[[-2 ;;]];
Most[x]
] &;
Comparison:
leoCL[lst_, f_] := Replace[lst, {left__, ntl_, l_} :> {left, f[ntl, l]}, {0}]
a = RandomInteger[1*^9, 5000];
Do[combineLast[a, Plus], {5000}] // Timing
Do[leoCL[a, Plus], {5000}] // Timing
{0.078, Null}
{1.844, Null}

Suppose 'list' is defined:
Remove[list];
list = {r1, r2, r2, r4, r5, a, b};
Re-set 'list' to be {r1, r2, r3, r4, r5, a} with the [[-1]] replaced by the sum of the last two elements in 'list'.
list = ReplacePart[Drop[list, -1], -1 -> Plus ## list[[-2 ;; -1]]]
Thanks for asking this, btw. :)

Here is my take on it:
addLastTwo = Function[Append[Drop[#, -2], Total[Take[#, -2]]]];
In[225]:= addLastTwo[{r1, r2, r3, r4, r5}]
Out[225]= {r1, r2, r3, r4 + r5}
This is slightly faster than Mr.Wizard's solution, although less general:
In[226]:= Do[addLastTwo#a, {10000}] // Timing
Out[226]= {0.25, Null}
In[227]:= Do[combineLast[a, Plus], {10000}] // Timing
Out[227]= {0.39, Null}

Related

DPLL algorithm procedure

I am trying to understand DPLL procedure before actually coding it.
For example, I have these clauses:
C1 : {c, !d, !b}
C2 : {d, a}
C3: {b, !d, !a}
C4: {d, c, b, a}
C5: {c, !d, !b}
C6: {d, c, b}
C7: {c}
Now I take the decision variable as d = 0, b = 0. The clause looks like this now.
C1: {c, 1, 1}
C2: {a}
C3: {1, !a}
C4: {c, a}
C5: {c, 1, 1}
C6: {c}
C7: {c}
How do unit propagation and pure literal rule play a part here?
Also, in C3 : {1, !a} - when I take a = 1, then this becomes {1, 0}. What should be the final value for this clause? Should it be {1}?
And if any clause has value {!b}, that is a negation of a literal, after applying the decision variable, then how to proceed?
That step wouldn't have happened that way, because there were unit clauses in the input which would have been resolved first.
{ c } (the clause) is a unit and its literal c is positive, therefore c (the variable) is forced to be 1, then we have
C2 : {d, a}
C3: {b, !d, !a}
as active clauses, because true clauses are ignored.
Now b is a pure literal (it wasn't always, but it became one since some clauses are not active anymore), but practical SAT solvers usually don't check for that except during pre-processing since it can't be checked efficiently.
And finally you would set d or a or both it doesn't matter.

Time efficient Partial Inverted Index building

I need to build a partial Inverted Index. Something like:
l = {{x, {h, a, b, c}}, {y, {c, d, e}}}
iI[l]
(*
-> {{a, {x}}, {b, {x}}, {c, {x, y}}, {d, {y}}, {e, {y}}, {h, {x}}}
*)
I think it is pretty clear what it does. In the input list, the {x, y ...} are unique, while the {a, b, c, ..} are not. The output ought to be ordered by #[[1]].
Right now, I am doing this:
iI[list_List] := {#, list[[Position[list, #][[All, 1]]]][[All, 1]]} & /#
(Union#Flatten#Last#Transpose#list)
But it looks too convoluted for such an easy task, seems too slow, and I should be able to cope with Legion.
A test drive to compare your results:
words = DictionaryLookup[];
abWords = DictionaryLookup["ab" ~~ ___];
l = {#, RandomChoice[abWords, RandomInteger[{1, 30}]]} & /# words[[1 ;; 3000]];
First#Timing#iI[l]
(*
-> 5.312
*)
So, any ideas for an speedup?
Seems a classic task for Reap-Sow (improvement in the final version due to #Heike):
iI[list_] := Sort[Reap[Sow ### list, _, List][[2]]]
Then,
iI[l]
{{a, {x}}, {b, {x}}, {c, {x, y}}, {d, {y}}, {e, {y}}, {h, {x}}}
and
In[22]:=
words=DictionaryLookup[];
abWords=DictionaryLookup["ab"~~___];
l={#,RandomChoice[abWords,RandomInteger[{1,30}]]}&/#words[[1;;3000]];
First#Timing#iI[l]
Out[25]= 0.047
EDIT
Here is an alternative version with a similar (slightly worse) performance:
iIAlt[list_] :=
Sort#Transpose[{#[[All, 1, 2]], #[[All, All, 1]]}] &#
GatherBy[Flatten[Thread /# list, 1], Last];
It is interesting that Reap - Sow here gives an even slightly faster solution than the one based on structural operations.
EDIT 2
Just for an illustration - for those who prefer rule-based solutions, here is one based on a combination of Dispatch and ReplaceList:
iIAlt1[list_] :=
With[{disp = Dispatch#Flatten[Thread[Rule[#2, #]] & ### list]},
Map[{#, ReplaceList[#, disp]} &, Union ## list[[All, 2]]]]
It is about 2-3 times slower than the other two, though.

Mathematica function with multiple IF[] conditionals

I have here a complicated bit of code that is not pretty nor easy to follow, but it represents a simplification of a larger body of code I am working with. I am a Mathematica novice and have already received some help on this issue from stackoverflow but it is still not solving my problem. Here is the code for which I hope you can follow along and assume what I am trying to get it to do. Thanks to you programming whizzes for the help.
a[b_, c_] = -3*b + 2*c + d + e + f;
g[b_, c_] := If[a[b, c] < 0, -3*a[b, c], a[b, c]];
h[T_, b_, c_] = (T/g[b, c]);
i[h_, T_, b_, c_] := If[h[T, b, c] > 0, 4*h[T, b, c], -5*h[T, b, c]];
j[b_, c_] := If[a[b, c] < 0, 5*a[b, c], 20*a[b, c]];
XYZ[h_, T_, i_, g_, j_, b_, c_] = T*i[h, T, b, c]*g[b, c] + j[b, c]
rules = {a -> 1, b -> 2, c -> 3, d -> 4, e -> 5, f -> 6, T -> 10};
XYZ[h, T, i, g, j, b, c] //. rules
Preserving as much of your code as possible, it will work with just a few changes:
a[b_, c_] := -3*b + 2*c + d + e + f;
g[b_, c_] := If[# < 0, -3 #, #] & # a[b, c]
h[T_, b_, c_] := T / g[b, c]
i[h_, T_, b_, c_] := If[# > 0, 4 #, -5 #] & # h[T, b, c]
j[b_, c_] := If[# < 0, 5 #, 20 #] & # a[b, c]
XYZ[h_, T_, i_, g_, j_, b_, c_] := T*i[h, T, b, c]*g[b, c] + j[b, c]
rules = {a -> 1, b -> 2, c -> 3, d -> 4, e -> 5, f -> 6, T -> 10};
XYZ[h, T, i, g, j, b, c] /. rules
(* Out= 700 *)
If statements are again externalized, as in the last problem.
all definitions are made with SetDelayed (:=), as a matter of good practice.
The presumed error T - 10 in your rules is corrected to T -> 10
Notice that again ReplaceRepeated (//.) is not needed, and is changed to /.
We still have a nonsensical rule a -> 1 but it does not cause a failure.

Pattern matching Inequality

I'd like to extract arguments from instances of Inequality. Following doesn't work, any idea why and how to fix it?
Inequality[1, Less, x, Less, 2] /. Inequality[a_, _, c_, _, e_] -> {a, c, e}
Inequality[1,Less,x,Less,2] /. HoldPattern[Inequality[a_,_,b_,_,c_]] -> {a, b, c}
Out: {1, x, 2}
Also, you can do this:
Inequality[1, Less, x, Less, 2] /.
Literal # Inequality[ a_ , _ , c_ , _ , e_ ] -> {a, c, e}
ADL
Why don't you use standard access to subexpression?
expr = Inequality[1, Less, x, Less, 2];
{a,c,e} = {expr[[1]], expr[[3]], expr[[5]]};

Multiple assignment between lists in Mathematica 7

Suppose there are two lists a = {a1, a2, a3} and b = {b1, b2, b3}, and I want to write an assignment statement to make a1=b1,a2=b2,a3=b3 which only refers to a and b:
Thread[a = b]
But it only makes a={b1,b2,b3}. Using := (SetDelayed) instead of = doesn't work either.
Any solution? Thanks.
I think the Thread only works on "explicit" lists; the variables need to be expanded before being operated on.
After some experimentation, this works for me:
a = {a1, a2, a3};
b = {b1, b2, b3};
Thread[Set[Evaluate#a, Evaluate#b]];
{a1, a2, a3}
You could also write Thread[Evaluate#a = Evaluate#b]; just depends whichever you find more readable.
What's wrong with
MapThread[Set,{{a1,a2,a3},{b1,b2,b3}}]
?
Here's another solution:
a = {a1, a2, a3};
b = {b1, b2, b3};
each[{x_, y_}, Transpose[{a, b}],
x = y]
Which uses my handy each function:
SetAttributes[each, HoldAll]; (* each[pattern, list, body] *)
each[pat_, lst_, bod_] := (* converts pattern to body for *)
Scan[Replace[#, pat:>bod]&, Evaluate#lst] (* each element of list. *)
Similarly, you can do this:
MapThread[(#1 = #2)&, {a, b}]
Well, if they are really called a1, a2, etc, you could do this:
Assign[x_, y_] := Module[{s1, s2, n, sn},
s1 = SymbolName[Unevaluated[x]];
s2 = SymbolName[Unevaluated[y]];
For[n = 1, n <= Length[x] && n <= Length[y], n++,
sn = ToString[n];
Evaluate[Symbol[s1 <> sn]] = Evaluate[Symbol[s2 <> sn]]
]
]
SetAttributes[Assign, HoldAll]
And then
Clear[b1, b2, b3];
Clear[a1, a2, a3];
a = {a1, a2, a3}
b = {b1, b2, b3}
Assign[a, b]
a
Gives the results for a, b and a again as:
{a1, a2, a3}
{b1, b2, b3}
{b1, b2, b3}
As expected.
In general you can create expressions like these from proper use of SymbolName and Symbol, but be careful with your evaluation. If I had written SymbolName[x] (without the Unevaluated) then it would've interpreted that as SymbolName[{a1, a2, a3}], which is clearly not desirable. Not using Evaluate on Symbol[s1 <> sn] will have Mathematica complain that you're trying to reassign the Symbol function.

Resources