What is the wrong in my code in mathematica - wolfram-mathematica
Assume that you play a variant of a poker game with five cards that is using a subset of one ordinary deck of cards. The subset considered is cards valued 7, 8, 9,10,J,Q,K,A from the one decks, in total 32 cards. Allow A-7-8-9-10 as a low straight or straight flush.
Calculate the exact probability of the following hands using the census method.
one pair
two pairs
three of a kind
straight
full house
flush
four of a kind
straight flush
nothing
Compare and discuss the probabilities of the above variant poker game to the probabilities for a normal poker game with a standard 52 card deck.
Note: If a given hand contains different valued hands only one (the highest rank) is considered
my solution was:
Any hand
In[172]:=
In[263]:= deck = Range[7, 13]
Out[263]= {7, 8, 9, 10, 11, 12, 13}
Subsets[{7, 8, 9, 10, A, J, Q, K}, {5}]
Out[41]= {{7, 8, 9, 10, A}, {7, 8, 9, 10, J}, {7, 8, 9, 10, Q}, {7, 8, 9, 10, K}, {7,
8, 9, A, J}, {7, 8, 9, A, Q}, {7, 8, 9, A, K}, {7, 8, 9, J, Q}, {7, 8, 9, J,
K}, {7, 8, 9, Q, K}, {7, 8, 10, A, J}, {7, 8, 10, A, Q}, {7, 8, 10, A,
K}, {7, 8, 10, J, Q}, {7, 8, 10, J, K}, {7, 8, 10, Q, K}, {7, 8, A, J,
Q}, {7, 8, A, J, K}, {7, 8, A, Q, K}, {7, 8, J, Q, K}, {7, 9, 10, A, J}, {7,
9, 10, A, Q}, {7, 9, 10, A, K}, {7, 9, 10, J, Q}, {7, 9, 10, J, K}, {7, 9,
10, Q, K}, {7, 9, A, J, Q}, {7, 9, A, J, K}, {7, 9, A, Q, K}, {7, 9, J, Q,
K}, {7, 10, A, J, Q}, {7, 10, A, J, K}, {7, 10, A, Q, K}, {7, 10, J, Q,
K}, {7, A, J, Q, K}, {8, 9, 10, A, J}, {8, 9, 10, A, Q}, {8, 9, 10, A,
K}, {8, 9, 10, J, Q}, {8, 9, 10, J, K}, {8, 9, 10, Q, K}, {8, 9, A, J,
Q}, {8, 9, A, J, K}, {8, 9, A, Q, K}, {8, 9, J, Q, K}, {8, 10, A, J, Q}, {8,
10, A, J, K}, {8, 10, A, Q, K}, {8, 10, J, Q, K}, {8, A, J, Q, K}, {9, 10,
A, J, Q}, {9, 10, A, J, K}, {9, 10, A, Q, K}, {9, 10, J, Q, K}, {9, A, J, Q,
K}, {10, A, J, Q, K}}
Length[Subsets[{7, 8, 9, 10, A, J, Q, K}, {5}]]
In[259]:= Subsets[{A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K}, {5}]
In[260]:= Length[Subsets[{A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K}, {5}]]
Out[260]= 1287
One pair:
32kort:
In[135]:= deck = Sort[Join[Range[7, 14], Range[7, 14], Range[7, 14], Range[7, 14]]];
hands = Subsets[deck, {5}];
onePairQ32[{___, x_, x_, ___}] := True;
onePairQ32[{___, x_, x_, x_, ___}] := False;
onePairQ32[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
onePairQ32[{___}] := False;
Count[hands, _?onePairQ32]
Out[141]= 107520
52kort:
In[128]:=
deck = Sort[Join[Range[1, 13], Range[1, 13], Range[1, 13], Range[1, 13]]];
hands = Subsets[deck, {5}];
onePairQ52[{___, x_, x_, ___}] := True;
onePairQ52[{___, x_, x_, x_, ___}] := False;
onePairQ52[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
onePairQ52[{___}] := False;
Count[hands, _?onePairQ52]
Out[134]= 1098240
Two pairs:
32kort:
In[8]:= deck = Sort[Join[Range[7, 14], Range[7, 14], Range[7, 14], Range[7, 14]]];
hands = Subsets[deck, {5}];
TwoPairQ32[{___, x_, x_, ___}] := False;
TwoPairQ32[{___, x_, x_, x_, ___}] := False;
TwoPairQ32[{___, x_, x_, ___, y_, y_, ___} /; x != y] := True;
TwoPairQ32[{___}] := False;
Count[hands, _?TwoPairQ32]
Out[14]= 24192
52kort:
In[15]:= deck = Sort[Join[Range[1, 13], Range[1, 13], Range[1, 13], Range[1, 13]]];
hands = Subsets[deck, {5}];
TwoPairQ52[{___, x_, x_, ___}] := False;
TwoPairQ52[{___, x_, x_, x_, ___}] := False;
TwoPairQ52[{___, x_, x_, ___, y_, y_, ___} /; x != y] := True;
TwoPairQ52[{___}] := False;
Count[hands, _?TwoPairQ52]
Out[21]= 123552
Three of a kind:
32kort:
In[22]:= deck = Sort[Join[Range[7, 14], Range[7, 14], Range[7, 14], Range[7, 14]]];
hands = Subsets[deck, {5}];
ThreeOfKindQ32[{___, x_, x_, ___}] := False;
ThreeOfKindQ32[{___, x_, x_, x_, ___}] := True;
ThreeOfKindQ32[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
ThreeOfKindQ32[{___}] := False;
Count[hands, _?ThreeOfKindQ32]
Out[28]= 12320
52kort:
In[142]:= deck = Sort[Join[Range[1, 13], Range[1, 13], Range[1, 13], Range[1, 13]]];
hands = Subsets[deck, {5}];
ThreeOfKindQ52[{___, x_, x_, ___}] := False;
ThreeOfKindQ52[{___, x_, x_, x_, ___}] := True;
ThreeOfKindQ52[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
ThreeOfKindQ52[{___}] := False;
Count[hands, _?ThreeOfKindQ52]
Out[148]= 59280
pairQ[{x_, x_, y_, y_} /; x != y] := False; (* two pairs *)
pairQ[{___, x_, x_, x_, ___}] := False; (* three of a kind *)
pairQ[{___, x_, x_, ___}] := True; (* a pair *)
pairQ[{___}] := False (* else *)
Four of a kind:
32kort:
In[36]:= deck = Sort[Join[Range[7, 14], Range[7, 14], Range[7, 14], Range[7, 14]]];
hands = Subsets[deck, {5}];
FourOfKindQ32[{___, x_, x_, ___}] := False;
FourOfKindQ32[{___, x_, x_, x_, ___}] := False;
FourOfKindQ32[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
FourOfKindQ32[{___}] := False;
FourOfKindQ32[{___, x_, x_, x_, x_, ___}] := True;
Count[hands, _?FourOfKindQ32]
Out[43]= 224
52kort:
In[44]:= deck = Sort[Join[Range[1, 13], Range[1, 13], Range[1, 13], Range[1, 13]]];
hands = Subsets[deck, {5}];
FourOfKindQ52[{___, x_, x_, ___}] := False;
FourOfKindQ52[{___, x_, x_, x_, ___}] := False;
FourOfKindQ52[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
FourOfKindQ52[{___}] := False;
FourOfKindQ52[{___, x_, x_, x_, x_, ___}] := True;
Count[hands, _?FourOfKindQ52]
Out[51]= 624
Full house:
32kort:
In[98]:= deck = Sort[Join[Range[7, 14], Range[7, 14], Range[7, 14], Range[7, 14]]];
hands = Subsets[deck, {5}];
FullhouseQ32[{___, x_, x_, ___}] := False;
FullhouseQ32[{___, x_, x_, x_, ___}] := False;
FullhouseQ32[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
FullhouseQ32[{___}] := False;
FullhouseQ32[{x_, x_, x_, y_, y_} /; x != y] := True;
Count[hands, _?FullhouseQ32]
Out[105]= 672
52kort:
In[157]:= deck = Sort[Join[Range[1, 13], Range[1, 13], Range[1, 13], Range[1, 13]]];
hands = Subsets[deck, {5}];
FullhouseQ52[{___, x_, x_, ___}] := False;
FullhouseQ52[{___, x_, x_, x_, ___}] := False;
FullhouseQ52[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
FullhouseQ52[{___}] := False;
FullhouseQ52[{x_, x_, y_, y_, y_} /; x != y] := True;
Count[hands, _?FullhouseQ52]
Out[164]= 1872
Nothing:
32kort:
In[75]:= deck = Sort[Join[Range[7, 14], Range[7, 14], Range[7, 14], Range[7, 14]]];
hands = Subsets[deck, {5}];
NothingQ32[{___, x_, x_, ___}] := False;
NothingQ32[{___, x_, x_, x_, ___}] := False;
NothingQ32[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
NothingQ32[{___}] := True;
Count[hands, _?NothingQ32]
Out[81]= 57344
52kort:
In[165]:= deck = Sort[Join[Range[1, 13], Range[1, 13], Range[1, 13], Range[1, 13]]];
hands = Subsets[deck, {5}];
NothingQ52[{___, x_, x_, ___}] := False;
NothingQ52[{___, x_, x_, x_, ___}] := False;
NothingQ52[{___, x_, x_, ___, y_, y_, ___} /; x != y] := False;
NothingQ52[{___}] := True;
Count[hands, _?NothingQ52]
Out[171]= 1317888
I got wrong values but I don't know what my problem is
Your 3-of-a-kind hands includes 4-of-a-kind hands.
Examples:
Take[Union[Cases[hands,_?ThreeOfKindQ32]],20]
which displays
{{7, 7, 7, 7, 8}, {7, 7, 7, 7, 9}, {7, 7, 7, 7, 10}, {7, 7, 7, 7, 11},
{7, 7, 7, 7, 12}, {7, 7, 7, 7, 13}, {7, 7, 7, 7, 14}, {7, 7, 7, 8, 8},
{7, 7, 7, 8, 9}, {7, 7, 7, 8, 10}, {7, 7, 7, 8, 11}, {7, 7, 7, 8, 12},
{7, 7, 7, 8, 13}, {7, 7, 7, 8, 14}, {7, 7, 7, 9, 9}, {7, 7, 7, 9, 10},
{7, 7, 7, 9, 11}, {7, 7, 7, 9, 12}, {7, 7, 7, 9, 13}, {7, 7, 7, 9, 14}}
Next, either I've made a mistake or there is something wrong with your Full House patterns. When I scrape-n-paste your code for that it gives me zero for a count. I have not figured out what is going on with that. Can you start a fresh notebook and paste nothing but your posted code for that and evaluate it and see if you also get zero?
When I change that code to
FullhouseQ32[{___}] := False;
FullhouseQ32[{x_, x_, x_, y_, y_} /; x != y] := True;
FullhouseQ32[{x_, x_, y_, y_, y_} /; x != y] := True;
I get what seems to be correct result, but I can't be certain.
Related
Fitting Data in Mathematica
I want to fit this data to a trig function, as it is periodic. So far, this cubic model is my most accurate result. Data = {{0, 4.042704626}, {1, 2.078666417}, {2, 1.174751826}, {3, 0.3352687769}, {4, 0.2094025098}, {5, 0.0614347256}, {6, 0.06293313355}, {7, 0.1011425361}, {8, 0.2648436037}, {9, 0.385090841}, {10, 0.9986888931}, {11, 1.678591497}, {12, 2.508709496}, {13, 2.891178123}, {14, 3.06799026}, {15, 4.494100019}, {16, 6.881438472}, {17, 8.603483798}, {18, 9.519011051}, {19, 10.42667166}, {20, 11.2448024}, {21, 11.1889867}, {22, 10.53343323}, {23, 7.246675407}}; model = a*x^3 + b*x^2 + c*x + d; fit = NonlinearModelFit[Data, model, {a, b, c, d}, x] Show[ListPlot[Data, PlotStyle -> Red], Plot[fit[x], {x, 0, 23}]]
A quintic model would be better. model = a*x^5 + b*x^4 + c*x^3 + d*x^2 + e*x + f; fit = NonlinearModelFit[Data, model, {a, b, c, d, e, f}, x] Show[ListPlot[Data, PlotStyle -> Red], Plot[fit[x], {x, 0, 23}]]
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}}
Strings form list to function
I am using Mathematica version 5.2. I need to split it to function, and make a result.. I've created this monster: mx = {}; arg = {}; fun = {}; x =. y =. here are lists and arguments switchfunction2[y_] := Switch[y, 1, AppendTo[fun, Cos[Random[Integer, {1, 10}]]], 2, AppendTo[fun, Sin[Random[Integer, {1, 10}]]], 3, AppendTo[fun, Tan[Random[Integer, {1, 10}]]], 4, AppendTo[fun, Csc[Random[Integer, {1, 10}]]], 5, AppendTo[fun, Sec[Random[Integer, {1, 10}]]], 6, AppendTo[fun, Cot[Random[Integer, {1, 10}]]] ] and random functions Do[AppendTo[mx, Random[Integer, {1, 10}]], {i, 2}] mx[[1]] " has been chosed" mx[[2]] "argumments " Do[AppendTo[arg, Random[Integer, {1, 5}]], {i, mx[[2]]}] arg Do[switchfunction2 /# {arg[[i]]}, {i, mx[[2]]}] fun I want to obtain f[z_]:=fun[[1]]+fun[[2]]...
In this case, I would do something like mx = RandomInteger[{1, 10}, 2]; arg = RandomInteger[{1, 5}, mx[[2]]]; switch[y_] := Module[{f}, f = Switch[y, 1, Cos, 2, Sin, 3, Tan, 4, Csc, 5, Sec, 6, Cot]; f[RandomInteger[{1, 10}]]] fun = switch /# arg; Total[fun] Or without using a switch function: mx = RandomInteger[{1, 10}, 2] flist = RandomChoice[{Cos, Sin, Tan, Csc, Sec, Cot}, mx[[2]]]; fun = #[RandomInteger[{1, 10}]] & /# flist; Total[fun] Edit Here's a version that should work in Mathematica 5.2. mx = Table[Random[Integer, {1, 10}], {2}]; arg = Table[Random[Integer, {1, 5}], {mx[[2]]}]; switch[y_] := Module[{f}, f = Switch[y, 1, Cos, 2, Sin, 3, Tan, 4, Csc, 5, Sec, 6, Cot]; f[Random[Integer, {1, 10}]]] fun = switch /# arg; Total[fun] To make a function out of this you could wrap everything in a Module, e.g. f := Module[{mx, arg, switch}, mx = Random[Integer, {1, 10}]; arg = Table[Random[Integer, {1, 5}], {mx}]; switch[y_] := Module[{f}, f = Switch[y, 1, Cos, 2, Sin, 3, Tan, 4, Csc, 5, Sec, 6, Cot]; f[Random[Integer, {1, 10}]]]; Total[switch /# arg]]
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:
Optimising the game of life
I'm writing a game of life program in mathematica however there is a caveat in that I need to be able to apply the reproduction rules to some percentage of the cells, I want to try a new method using MapAt but liveNeighbors doesn't work elementwise, and I can't think of a way of fixing it without doing exactly what I did before (lots of messy indexing), does anyone have any suggestions? (I am assuming this will be more efficient then the old method, which is listed below, if not please let me know, I am just a beginner!). What I am trying to do: Map[ArrayPlot,FixedPointList[MapAt[update[#,liveNeighbors[#]]&,#,coords]&,Board, 1]] What I have done already: LifeGame[ n_Integer?Positive, steps_] := Module [{Board, liveNeighbors, update}, Board = Table [Random [Integer], {n}, {n}]; liveNeighbors[ mat_] := Apply[Plus,Map[RotateRight[mat,#]&,{{-1,-1},{-1, 0},{-1,1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}]]; update[1, 2] := 1; update[_, 3] := 1; update[ _, _] := 0; SetAttributes[update, Listable]; Seed = RandomVariate[ProbabilityDistribution[0.7 UnitStep[x] + 0.3 UnitStep[x - 1], {x, 0, 1, 1}], {n, n}]; FixedPointList[Table[If[Seed[[i, j]] == 1,update[#[[i, j]], liveNeighbors[#][[i, j]]],#[[i, j]]], {i, n}, {j, n}]&, Board, steps]]] Thanks!
In[156]:= LifeGame2[n_Integer?Positive, steps_] := Module[{Board, liveNeighbors, update}, Board = RandomInteger[1, {n, n}]; liveNeighbors[mat_] := ListConvolve[{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, ArrayPad[mat, 1, "Periodic"]]; SetAttributes[update, Listable]; Seed = RandomVariate[BernoulliDistribution[0.3], {n, n}]; update[0, el_, nei_] := el; update[1, 1, 2] := 1; update[1, _, 3] := 1; update[1, _, _] := 0; FixedPointList[MapThread[update, {Seed, #, liveNeighbors[#]}, 2] &, Board, steps] ] This implementation does the same as yours, except is quite a lot faster: In[162]:= AbsoluteTiming[ res1 = BlockRandom[SeedRandom[11]; LifeGame[20, 100]];] Out[162]= {6.3476347, Null} In[163]:= Timing[BlockRandom[Seed[11]; LifeGame2[20, 100]] == res1] Out[163]= {0.047, True}
Assuming you don't have to roll your own code for a homework problem, have you considered just using the built-in CellularAutomaton function? Straight from the documentation, the 2D CA rule: GameOfLife = {224, {2, {{2, 2, 2}, {2, 1, 2}, {2, 2, 2}}}, {1, 1}}; And iterate over a 100x100 grid for 100 steps: ArrayPlot[CellularAutomaton[GameOfLife, RandomInteger[1, {100, 100}], {{{100}}}]] It would at least give you a baseline for a speed comparison. Instead of MapAt, you could use Part with the Span syntax to replace a whole subarray at once: a = ConstantArray[0, {5, 5}]; a[[2 ;; 4, 2 ;; 4]] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} HTH!
Here you have my golfed version.