How to remove an extra {} in this use of DeleteCases - wolfram-mathematica

(Mathematica version: 8.0.4)
Given
lst = {{{{1, 2}, 3}, {{4, 5}, 6}}, {{{7, 8, 9, 10, 11}, 13}}};
lst2 = DeleteCases[lst, {x_, y_} /; y > 6, {2}]
gives
{{{{1, 2}, 3}, {{4, 5}, 6}}, {}}
Note the extra empty {} at the end.
I could not find a way to remove it in the same command using DeleteCases (which I think the right command to use for this), so I had to apply it again on the result
lst2 = DeleteCases[lst2, {}]
{{{{1, 2}, 3}, {{4, 5}, 6}}}
question: Is there a trick to do the above in one command without getting the empty {} in the result? so that the command is self contained for all cases?
updatet 1
response to Lou suggestion below, of adding an extra { }
Here is an example where I get different results:
lst={{{{1, 2}, 3}, {{4, 5}, 6}}, {{{7, 8, 9, 10, 11}, 13}}}
now using the method of removing empty {} by an extra application of DeleteCases, we get
lst2 = DeleteCases[lst, {x_, y_} /; y >= 6, {2}]
{{{{1, 2}, 3}}, {}}
lst2 = DeleteCases[lst2, {}]
{{{{1, 2}, 3}}}
now using the method of extra { }
lst2 = DeleteCases[lst, {{x_, y_}} /; y >= 6]
{{{{1, 2}, 3}, {{4, 5}, 6}}}
which is the not the same, I should get only {{{{1, 2}, 3}}}
thanks

There seems to be no general automatic way to remove empty lists which emerge as a result of DeleteCases or other structural transformation function, as a part of the original structural operation. Their removal must be a separate operation. This question:
efficient-way-to-remove-empty-lists-from-lists
answers how to do that efficiently after the fact

I think that your original solution is a good solution:
$lst = {{{{1, 2}, 3}, {{4, 5}, 6}}, {{{7, 8, 9, 10, 11}, 13}}};
DeleteCases[$lst, {x_, y_} /; y > 6, {2}] // DeleteCases[#, {}] &
It is clear and concise. An alternative would be this:
DeleteCases[$lst, {x_, y_} /; y > 6, {2}] /. {} -> Sequence[]
However, let's persevere and try to find a way to do the job with a single invocation of DeleteCases. We could add an alternative pattern that matches top-level elements that contain only rejected subpairs:
DeleteCases[
$lst
, (a:{{_, _?NumericQ}..} /; And ## Map[#[[2]] > 6 &, a, {1}]) |
({_, y_?NumericQ} /; y > 6)
, {1, 2}
]
It is inconvenient to write the threshold value (6) twice. We can avoid that:
DeleteCases[
$lst
, 6 /. n_ :>
(a:{{_, _?NumericQ}..} /; And ## Map[#[[2]] > n &, a, {1}]) |
({_, y_?NumericQ} /; y > n)
, {1, 2}
]
Alternatively, we could define a local function that matches both top-level elements and individual subpairs:
Module[{test}
, test[elems:{{_, _?NumericQ}..}] := And ## test /# elems
; test[{_List, y_?NumericQ}] := y > 6
; DeleteCases[$lst, e_?test, {1, 2}]
]
While these proposals meet the stated requirement to invoke DeleteCases only once, I find them unsatisfactory. My main objection is that they are not as readable as the original solution.

lst2 = DeleteCases[DeleteCases[lst, {x_, y_} /; y > 6, {2}], {}]

lst2 = DeleteCases[lst, {{x_, y_}} /; y > 6]
But I suppose you want the first list to be matched to..?
Perhaps:
lst2 = DeleteCases[Flatten[lst,1], {x_, y_} /; y >= 6]
it results in {{{1, 2}, 3}}

The other answers are all very good, and I hesitate to give this reply.
The following is just for fun, nothing more:
lst = {{{{1, 2}, 3}, {{4, 5}, 6}}, {{{7, 8, 9, 10, 11}, 13}}};
Using Cases
Cases[lst, {x_, y_} /; ! y > 6, {2}]
Cases[lst, {x_, y_} /; ! y >= 6, {2}]
giving
{{{1, 2}, 3}, {{4, 5}, 6}}
{{{1, 2}, 3}}

Why not just use an OR clause in DeleteCases and get delete based on the pattern OR a {}
DeleteCases[lst, {x_, y_} /; y > 6 | {}, {2} ]
On my machine that returns the result:
{{{{1, 2}, 3}, {{4, 5}, 6}}, {{{7, 8, 9, 10, 11}, 13}}}
...which is what I think you wanted.

Related

binning an array to create sum domains array

In Mathematica - how do I bin an array to create a new array which consist from sum domains of the old array with a given size ???
Example:
thanks.
This is slightly simpler than #ChrisDegnen's solution. Given the same definition of array the expression
Map[Total, Map[Flatten, Partition[array, {2, 2}], {2}], {2}]
produces
{{4, 10}, {8, 10}}
If you prefer, this expression
Apply[Plus, Map[Flatten, Partition[array, {2, 2}], {2}], {2}]
uses Apply and Plus rather than Map and Total but is entirely equivalent.
This works for the example but a generalised version would need more work.
array =
{{1, 1, 1, 2},
{1, 1, 3, 4},
{2, 2, 2, 3},
{2, 2, 2, 3}};
Map[Total,
Map[Flatten,
Map[Transpose,
Map[Partition[#, 2] &, Partition[array, 2], 2],
2], {2}], {2}]
% // MatrixForm
4 10
8 10

Variant on Cutting Stock in Mathematica

So I'm pretty new to Mathematica, and am trying to learn to solve problems in a functional way. The problem I was solving was to list the ways in which I could sum elements from a list (with repetitions), so the sum is leq to some value. The code below solves this just fine.
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"]}]
However, the code check a lot of unneccesary cases, which could be a problem if m is higher of the list is longer. My question is simply what would be the most Mathematica-esque way of solving this problem, concerning both efficiency and code elegancy.
One simple though not optimal way is :
sol = Reduce[Dot[i, {a, b, c, d, e}] <= m, {a, b, c, d, e}, Integers];
at first try with a smaller i, say i = {7.25, 7.75} to get a feeling about whether you can use this.
You can improve speed by providing upper limits for the coefficients, like in
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]
How about
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]
];
);
So that
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}}

find the min and max of the set of prime factor of a number with the same power in Mathematica

Let
n=2^10 3^7 5^4...31^2...59^2 61...97
be the factorization of an integer such that the powers of primes are non-increasing.
I would like to write a code in Mathematica to find Min and Max of prime factor of n such that they have the same power.
for example I want a function which take r(the power) and give (at most two) primes in general. A specific answer for the above sample is
minwithpower[7]=3
maxwithpower[7]=3
minwithpower[2]=31
maxwithpower[2]=59
Any idea please.
Let n = 91065388654697452410240000 then
FactorInteger[n]
returns
{{2, 10}, {3, 7}, {5, 4}, {7, 4}, {31, 2}, {37, 2}, {59, 2}, {61, 1}, {97, 1}}
and the expression
Cases[FactorInteger[n], {_, 2}]
returns only those elements from the list of factors and coefficients where the coefficient is 2, ie
{{31, 2}, {37, 2}, {59, 2}}
Next, the expression
Cases[FactorInteger[n], {_, 2}] /. {{min_, _}, ___, {max_, _}} -> {min, max}
returns
{31, 59}
Note that this approach fails if the power you are interested in only occurs once in the output from FactorInteger, for example
Cases[FactorInteger[n], {_, 7}] /. {{min_, _}, ___, {max_, _}} -> {min, max}
returns
{{3, 7}}
but you should be able to fix that deficiency quite easily.
One solution is :
getSamePower[exp_, n_] := With[{powers =
Select[ReleaseHold[n /. {Times -> List, Power[a_, b_] -> {a, b}}], #[[2]] ==
exp &]},
If[Length[powers] == 1, {powers[[1, 1]], powers[[1, 1]]}, {Min[powers[[All, 1]]], Max[powers[[All, 1]]]}]]
to be used as :
getSamePower[7, 2^10 3^7 5^4 \[Pi]^1 31^2 E^1 59^2 61^1 I^1 97^1 // HoldForm]
(* {3, 3} *)
getSamePower[2, 2^10 3^7 5^4 \[Pi]^1 31^2 E^1 59^2 61^1 I^1 97^1 // HoldForm]
(* {31, 59} *)

Overlapping strips

Suppose I have a series of strips of paper placed along an infinite ruler, with start and end points specified by pairs of numbers. I would like to create a list representing the number of layers of paper at points along the ruler.
For example:
strips =
{{-27, 20},
{ -2, -1},
{-47, -28},
{-41, 32},
{ 22, 31},
{ 2, 37},
{-28, 30},
{ -7, 39}}
Should output:
-47 -41 -27 -7 -2 -1 2 20 22 30 31 32 37 39
1 2 3 4 5 4 5 4 5 4 3 2 1 0
What is the most efficient, clean, or terse way to do this, accommodating Real and Rational strip positions?
Here's one approach:
Clear[hasPaper,nStrips]
hasPaper[y_, z_] := Piecewise[{{1, x <= z && x >= y}}, 0];
nStrips[y_, strip___] := Total#(hasPaper ### strip) /. x -> y
You can get the number of strips at any value.
Table[nStrips[i, strips], {i, Sort#Flatten#strips}]
{1, 2, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1}
Also, plot it
Plot[nStrips[x, strips], {x, Min#Flatten#strips, Max#Flatten#strips}]
Here is one solution:
In[305]:=
strips = {{-27, 20}, {-2, -1}, {-47, -28}, {-41, 32}, {22, 31}, {2,
37}, {-28, 30}, {-7, 39}};
In[313]:= int = Interval /# strips;
In[317]:= Thread[{Union[Flatten[strips]],
Join[Count[int, x_ /; IntervalMemberQ[x, #]] & /# (Mean /#
Partition[Union[Flatten[strips]], 2, 1]), {0}]}]
Out[317]= {{-47, 1}, {-41, 2}, {-28, 2}, {-27, 3}, {-7, 4}, {-2,
5}, {-1, 4}, {2, 5}, {20, 4}, {22, 5}, {30, 4}, {31, 3}, {32,
2}, {37, 1}, {39, 0}}
EDIT Using SplitBy and postprocessing the following code gets the shortest list:
In[329]:=
strips = {{-27, 20}, {-2, -1}, {-47, -28}, {-41, 32}, {22, 31}, {2,
37}, {-28, 30}, {-7, 39}};
In[330]:= int = Interval /# strips;
In[339]:=
SplitBy[Thread[{Union[Flatten[strips]],
Join[Count[int, x_ /; IntervalMemberQ[x, #]] & /# (Mean /#
Partition[Union[Flatten[strips]], 2, 1]), {0}]}],
Last] /. {b : {{_, co_} ..} :> First[b]}
Out[339]= {{-47, 1}, {-41, 2}, {-27, 3}, {-7, 4}, {-2, 5}, {-1,
4}, {2, 5}, {20, 4}, {22, 5}, {30, 4}, {31, 3}, {32, 2}, {37,
1}, {39, 0}}
You may regard this as a silly approach, but I'll offer it anyway:
f[x_]:=Sum[UnitStep[x-strips[[k,1]]]-UnitStep[x-strips[[k,2]]],{k,Length[strips]}]
f/#Union[Flatten[strips]]
f[u_, s_] := Total[Piecewise#{{1, #1 <= x < #2}} & ### s /. x -> u]
Usage
f[#, strips] & /# {-47, -41, -27, -7, -2, -1, 2, 20, 22, 30, 31, 32, 37, 39}
->
{1, 2, 3, 4, 5, 4, 5, 4, 5, 4, 3, 2, 1, 0}
For Open/Closed ends, just use <= or <
Here's my approach, similar to belisarius':
strips = {{-27, 20}, {-2, -1}, {-47, -28}, {-41, 32}, {22, 31}, {2,
37}, {-28, 30}, {-7, 39}};
pw = PiecewiseExpand[Total[Boole[# <= x < #2] & ### strips]]
Grid[Transpose[
SplitBy[SortBy[Table[{x, pw}, {x, Flatten[strips]}], First],
Last][[All, 1]]], Alignment -> "."]
Here's my attempt - it works on integers, rationals and reals, but makes no claim to being terribly efficient. (I made the same mistake as Sasha, my original version did not return the shortest list. So I stole the SplitBy fix!)
layers[strips_?MatrixQ] := Module[{equals, points},
points = Union#Flatten#strips;
equals = Function[x, Evaluate[(#1 <= x < #2) & ### strips]];
points = {points, Total /# Boole /# equals /# points}\[Transpose];
SplitBy[points, Last] /. {b:{{_, co_}..} :> First[b]}]
strips = {{-27, 20}, {-2, -1}, {-47, -28}, {-41, 32}, {22, 31},
{2, 37}, {-28, 30}, {-7, 39}};
In[3]:= layers[strips]
Out[3]= {{-47, 1}, {-41, 2}, {-27, 3}, {-7, 4}, {-2, 5}, {-1, 4}, {2, 5},
{20, 4}, {22, 5}, {30, 4}, {31, 3}, {32, 2}, {37, 1}, {39, 0}}
In[4]:= layers[strips/2]
Out[4]:= {{-(47/2), 1}, {-(41/2), 2}, {-(27/2), 3}, {-(7/2), 4},
{-1, 5}, {-(1/2), 4}, {1, 5}, {10, 4}, {11, 5}, {15, 4}, {31/2, 3},
{16, 2}, {37/2, 1}, {39/2, 0}}
In[5]:= layers[strips/3.]
Out[5]= {{-15.6667, 1}, {-13.6667, 2}, {-9., 3}, {-2.33333, 4}, {-0.666667, 5},
{-0.333333, 4}, {0.666667, 5}, {6.66667, 4}, {7.33333, 5}, {10.,4},
{10.3333, 3}, {10.6667, 2}, {12.3333, 1}, {13., 0}}
Splice together abutting strips, determine key points where number of layers
changes, and calculate how many strips each key point inhabits:
splice[s_, {}] := s
splice[s_, vals_] := Module[{h = First[vals]},
splice[(s /. {{x___, {k_, h}, w___, {h, j_}, z___} :> {x, {k, j},
w, z}, {x___, {k_, h}, w___, {h, j_}, z___} :> {x, {k, j}, w,
z}}), Rest[vals]]]
splicedStrips = splice[strips, Union#Flatten#strips];
keyPoints = Union#Flatten#splicedStrips;
({#, Total#(splicedStrips /. {a_, b_} :> Boole[a <= # < b])} & /# keyPoints)
// Transpose // TableForm
EDIT
After some struggling I was able to remove splice and more directly eliminate points that did not need checking (-28, in the strips data we've been using) :
keyPoints = Complement[pts = Union#Flatten#strips,
Cases[pts, x_ /; MemberQ[strips, {x, _}] && MemberQ[strips, {_, x}]]];
({#, Total#(strips /. {a_, b_} :> Boole[a <= # < b])} & /# keyPoints)
One approach of solving this is converting the strips
strips = {{-27, 20}, {-2, -1}, {-47, -28}, {-41, 32}
,{ 22, 31}, { 2, 37}, {-28, 30}, {-7, 39}}
to a list of Delimiters, marking the beginning or end of a strip and sort them by position
StripToLimiters[{start_, end_}] := Sequence[BeginStrip[start], EndStrip[end]]
limiterlist = SortBy[StripToLimiters /# strips, First]
Now we can map the sorted limiters to increments/decrements
LimiterToDiff[BeginStrip[_]] := 1
LimiterToDiff[EndStrip[_]] := -1
and use Accumulate to get the intermediate totals of intersected strips:
In[6]:= Transpose[{First/##,Accumulate[LimiterToDiff/##]}]&[limiterlist]
Out[6]= {{-47,1},{-41,2},{-28,3},{-28,2},{-27,3},{-7,4},{-2,5},{-1,4}
,{2,5},{20,4},{22,5},{30,4},{31,3},{32,2},{37,1},{39,0}}
Or without the intermediate limiterlist:
In[7]:= StripListToCountList[strips_]:=
Transpose[{First/##,Accumulate[LimiterToDiff/##]}]&[
SortBy[StripToLimiters/#strips,First]
]
StripListToCountList[strips]
Out[8]= {{-47,1},{-41,2},{-28,3},{-28,2},{-27,3},{-7,4},{-2,5},{-1,4}
,{2,5},{20,4},{22,5},{30,4},{31,3},{32,2},{37,1},{39,0}}
The following solution assumes that the layer count function will be called a large number of times. It uses layer precomputation and Nearest in order to greatly reduce the amount of time required to compute the layer count at any given point:
layers[strips:{__}] :=
Module[{pred, changes, count}
, changes = Union # Flatten # strips /. {c_, r___} :> {c-1, c, r}
; Evaluate[pred /# changes] = {changes[[1]]} ~Join~ Drop[changes, -1]
; Do[count[x] = Total[(Boole[#[[1]] <= x < #[[2]]]) & /# strips], {x, changes}]
; With[{n = Nearest[changes]}
, (n[#] /. {m_, ___} :> count[If[m > #, pred[m], m]])&
]
]
The following example uses layers to define a new function f that will compute the layer count for the provided sample strips:
$strips={{-27,20},{-2,-1},{-47,-28},{-41,32},{22,31},{2,37},{-28,30},{-7,39}};
f = layers[$strips];
f can now be used to compute the number of layers at a point:
Union # Flatten # $strips /. s_ :> {s, f /# s} // TableForm
Plot[f[x], {x, -50, 50}, PlotPoints -> 1000]
For 1,000 layers and 10,000 points, the precomputation stage can take quite a bit of time, but individual point computation is relatively quick:

Changing values in nested lists according to elements in the list

I have a list of pairs of values in mathematica, for example List= {{3,1},{5,4}}.
How do I change the first element (3 & 5) if the second element does not reach a threshold. For example, if the second parts are below 2 then i wish the first parts to go to zero. so that list then = {{0,1},{5,4}}. Some of these lists are extremely long so manually doing it is not an option, unfortunately.
Conceptually, the general way is to use Map. In your case, the code would be
In[13]:= lst = {{3, 1}, {5, 4}}
Out[13]= {{3, 1}, {5, 4}}
In[14]:= thr = 2
Out[14]= 2
In[15]:= Map[{If[#[[2]] < thr, 0, #[[1]]], #[[2]]} &, lst]
Out[15]= {{0, 1}, {5, 4}}
The # symbol here stands for the function argument. You can read more on pure functions here. Double square brackets stand for the Part extraction. You can make it a bit more concise by using Apply on level 1, which is abbreviated by ###:
In[27]:= {If[#2 < thr, 0, #], #2} & ### lst
Out[27]= {{0, 1}, {5, 4}}
Note however that the first method is several times faster for large numerical lists. An even faster, but somewhat more obscure method is this:
In[29]:= Transpose[{#[[All, 1]]*UnitStep[#[[All, 2]] - thr], #[[All, 2]]}] &[lst]
Out[29]= {{0, 1}, {5, 4}}
It is faster because it uses very optimized vectorized operations which apply to all sub-lists at once. Finally, if you want the ultimate performance, this procedural compiled to C version will be another factor of 2 faster:
fn = Compile[{{lst, _Integer, 2}, {threshold, _Real}},
Module[{copy = lst, i = 1},
For[i = 1, i <= Length[lst], i++,
If[copy[[i, 2]] < threshold, copy[[i, 1]] = 0]];
copy], CompilationTarget -> "C", RuntimeOptions -> "Speed"]
You use it as
In[32]:= fn[lst, 2]
Out[32]= {{0, 1}, {5, 4}}
For this last one, you need a C compiler installed on your machine.
Another alternative: Apply (###, Apply at level 1) and Boole (turns logical values in 1's and 0's):
lst = {{3, 1}, {5, 4}};
{#1 Boole[#2 >= 2], #2} & ### lst
An alternative approach might be to use substitution rules, and attach a condition (/;)
lst = {{3, 1}, {5, 4}};
lst /. {x_, y_ /; y < 2} -> {0, y}
output:
{{0, 1}, {5, 4}}
Assuming that your matrix is 2x2 and by second elemnt you mean the second row:
This should work:
If[A[[2, 1]] < 2 || A[[2, 2]] < 2, A[[2,1]] = 0 ]; A
You may have to change the variables, since your questions is kind of confusing. But that's the idea ;-)

Resources