Reordering using Patterns in Mathematica - wolfram-mathematica

Trying to do this :
list={{{33, 105, 203, 295}, {34, 106, 204, 296}},
{{21, 135, 201, 333}, {22,136, 202, 334}}}
I would like to transform sublists so that the first one:
{{33, 105, 203, 295}, {34, 106, 204, 296}}
becomes
{{33, 204, 106, 295}, {34, 106, 105, 296}}
I don`t understand what I am doing wrong in the following :
list /. {{a_,b_,c_,d_}, {e_,f_,g_,h_}} :>
{{a_,g_,f_,d_}, {e_,c_,b_,h_}}
EDIT
Thanks to Leonid`s Comment, the below now works
list /. {{a_,b_,c_,d_}, {e_,f_,g_,h_}} :>
{{a,g,f,d}, {e,c,b,h}}
If somebody knows a better way to do this, don`t hesitate.

As Leonid wrote, but declined to post as an answer, your pattern works once it is corrected:
list /. {{a_,b_,c_,d_}, {e_,f_,g_,h_}} :> {{a, g, f, d}, {e, c, b, h}}
This is the most direct way to accomplish this task, but as Leonid also wrote, it is not the most general. Here is another way, admittedly without patterns, that you might approach this:
orderBy[list_, order_] := Partition[Flatten[#][[order]], 4] & /# list
orderBy[list, {1, 7, 6, 4, 5, 3, 2, 8}]
This allows you to specify the reordering as a simple permuation, easily written by hand, or generated with RandomeSample#Range#8.
If your data has more variety of shape, this can be extended with different Partition parameters, etc.

Related

Exact orthogonalization of vectors in Wolfram

What I have is a matrix, I need to orthogonolize its eigen vectors.
That is basically all I need, but in exact form.
So here is my wolfram input
(orthogonolize(eigenvectors({{146, 112, 78, 17, 122}, {112, 86, 60, 13, 94}, {78, 60, 42 , 9, 66}, {17, 13, 9, 2, 14}, {122, 94, 66, 14, 104}})))
That gives me float numbers, while I need the exact forms.
Any ways to fix this?
Wolfram Mathematica, not WolframAlpha which is a completely different product with different rules and gives different results, given this
FullSimplify[Orthogonalize[Eigenvectors[{
{146, 112, 78, 17, 122}, {112, 86, 60, 13, 94}, {78, 60, 42 , 9, 66},
{17, 13, 9, 2, 14}, {122, 94, 66, 14, 104}}]]]
returns this exact form
{{Sqrt[121/342 + 52/(9*Sqrt[35587])], Sqrt[5/38 + 18/Sqrt[35587]],
Sqrt[25/342 + 64/(9*Sqrt[35587])], Sqrt[7/38 - 26/Sqrt[35587]]/3,
2*Sqrt[2/19 - 7/Sqrt[35587]]},
{-1/3*Sqrt[121/38 - 52/Sqrt[35587]], -Sqrt[5/38 - 18/Sqrt[35587]],
Sqrt[25/38 - 64/Sqrt[35587]]/3, -1/3*Sqrt[7/38 + 26/Sqrt[35587]],
Sqrt[8/19 + 28/Sqrt[35587]]},
{3/Sqrt[35], -Sqrt[5/7], 0, 0, 1/Sqrt[35]},
{-11/Sqrt[5110], -Sqrt[5/1022], 0, Sqrt[70/73], 4*Sqrt[2/2555]},
{-17/(3*Sqrt[2774]), -7/Sqrt[2774], Sqrt[146/19]/3, Sqrt[2/1387]/3, -9*Sqrt[2/1387]}}
Think of at least two different ways you can check that for correctness before you depend on that.
The last three of those can be simplified somewhat
1/Sqrt[35]*{3,-5,0,0,1},
1/Sqrt[5110]*{-11,-5,0,70,8},
1/(3*Sqrt[2774])*{-17,-21,146,2,-54}
but I cannot yet see a way to simplify the first two to a third of their current size. Can anyone else see a way to do that? Please check these results very carefully.

Prolog: Reverse function of string_to_list

I know the Prolog-builtin "string_to_list". Now i need to reverse its functionality.
?- string_to_list('a*1+2', L).
L = [97, 42, 49, 43, 50].
How can i reverse this? Is there a builtin function?
Anything that does what "desiredfunction" does, would be a great help.
?- desiredfunction([97, 42, 49, 43, 50], R).
R = 'a*1+2'.
Thank you.
string_to_list/2 is deprecated in favor of string_codes/2.
The predicate is bidirectional, meaning that you can plug in a list, and get a string back on the other side.
string_codes(R, [97, 42, 49, 43, 50])
Better yet, use atom_codes/2, which is also bidirectional, and is more widely supported among Prolog implementations:
atom_codes(R, [97, 42, 49, 43, 50])
This produces
a*1+2

prolog - not a function warning

I have this Prolog program where I want to match players with players with the same level (newbie, intermediate, or expert) and server:
player(player29, 408, 183, europe).
player(player30, 462, 97, north-america).
player(player31, 25, 22, asia).
player(player32, 481, 248, asia).
player(player33, 111, 37, asia).
player(player34, 424, 359, north-america).
player(player35, 381, 358, asia).
player(player36, 231, 159, africa).
player(player37, 31, 20, africa).
player(player38, 22, 21, africa).
player(player39, 144, 35, oceania).
player(player40, 30, 25, asia).
player(player41, 221, 112, south-america).
player(player42, 344, 292, africa).
player(player43, 183, 148, asia).
player(player44, 62, 40, africa).
player(player45, 281, 23, north-america).
player(player46, 308, 173, south-america).
player(player47, 127, 125, asia).
player(player48, 441, 393, south-america).
player(player49, 213, 48, oceania).
player(player50, 343, 145, africa).
winrate(X):-player(X, T, W, _); (W/T) * 100.
newbie(X):-winrate(X) < 40.
intermediate(X):-winrate(X) >=40; winrate(X) < 80.
expert(X):-winrate(X) > 80.
However, I get a warning saying "Arithmetic: 'winrate(_G1082)' is not a function" when I compile it. Can someone explain to me what that means?
If I could nominate a misconception in Prolog for greatest all-time beginner stumbling block, it would be this: there is no such thing as a return value in Prolog. So the problem comes down to this definition:
winrate(X) :- player(X, T, W, _); (W/T) * 100.
If you type just that into Prolog, you'll get a mysterious looking warning message:
Warning: user://1:9:
Singleton variable in branch: T
Singleton variable in branch: W
I suspect you think that clause says "Look up T and W for player X and return W/T * 100." What Prolog actually thinks you said there is "Look up T and W for player X, or something over something times one hundred <awkward pause>" which is not particularly meaningful. When you ask winrate(player47), Prolog will stand in the corner with its hands in its pockets and say "um, true?"
The correction is this:
winrate(X, Rate) :- player(X, T, W, _), Rate is (W/T) * 100.
You have the exact same problem a little further down in newbie/1 et. al.: winrate(X) < 40 does not have intrinsic meaning in Prolog, because there is no "return value" in Prolog. The corrected expression is winrate(X, WinRate), WinRate < 40.
Note that there is nothing special about the last argument in Prolog. It's common for predicates with one-way semantics to use the last arguments for results, but it isn't really a law and Prolog is not enforcing anything there.
Pay close attention to singleton variable errors. Nothing meaningful happens in Prolog without variables appearing more than once, so if you get this error and you immediately replace the named variables with _, does your clause still seem to have enough information to do its work? If not, you have almost certainly missed something or are confused about Prolog's semantics. Believe me, I learned this one from experience.

Collatz Conjecture in Mathematica

I am new to Mathematica and am trying to understand patterns and rules. So I tried the following:
A = {1, 2, 3, 4}
A //. {x_?EvenQ -> x/2, x_?OddQ -> 3 x + 1}
This is based on: http://en.wikipedia.org/wiki/Collatz_conjecture
This is supposed to converge, but what I got is:
ReplaceRepeated::rrlim: Exiting after {1,2,3,4} scanned 65536 times. >>
Please help me understand my error in the pattern/rule.
Regards
The way you wrote this, it does not terminate, so it eg ends up alternating between 1 and 4, 2 etc. (all recursive descriptions must eventually bottom out somewhere, and your does not include a case to do that at n=1).
This works:
ClearAll[collatz];
collatz[1] = 1;
collatz[n_ /; EvenQ[n]] := collatz[n/2]
collatz[n_ /; OddQ[n]] := collatz[3 n + 1]
although it does not give a list of the intermediate results. A convenient way to get them is
ClearAll[collatz];
collatz[1] = 1;
collatz[n_ /; EvenQ[n]] := (Sow[n]; collatz[n/2])
collatz[n_ /; OddQ[n]] := (Sow[n]; collatz[3 n + 1])
runcoll[n_] := Last#Last#Reap[collatz[n]]
runcoll[115]
(*
-> {115, 346, 173, 520, 260, 130, 65, 196, 98, 49, 148, 74, 37, 112, 56,
28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1}
*)
or
colSeq[x_] := NestWhileList[
Which[
EvenQ[#], #/2,
True, 3*# + 1] &,
x,
# \[NotEqual] 1 &]
so that eg
colSeq[115]
(*
-> {115, 346, 173, 520, 260, 130, 65, 196, 98, 49, 148, 74, 37, 112, 56,
28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1}
*)
By the way the fastest approach I could come up with (I think I needed it for some project Euler problem) was something like
Clear#collatz;
collatz[1] := {1}
collatz[n_] := collatz[n] = If[
EvenQ[n] && n > 0,
{n}~Join~collatz[n/2],
{n}~Join~collatz[3*n + 1]]
compare:
colSeq /# Range[20000]; // Timing
(*
-> {6.87047, Null}
*)
while
Block[{$RecursionLimit = \[Infinity]},
collatz /# Range[20000];] // Timing
(*
-> {0.54443, Null}
*)
(we need to increase the recursion limit to get this to run correctly).
You got the recursive cases right, but you have no base case to terminate the recursion which leads to infinite recursion (or until Mathematica hits the pattern replacement limit). If you stop when you reach 1, it works as expected:
In[1]:= A = {1,2,3,4}
Out[1]= {1,2,3,4}
In[2]:= A //. {x_?EvenQ /; x>1 -> x/2, x_?OddQ /; x>1 -> 3 x+1}
Out[2]= {1,1,1,1}
In the documentation center, the section about writing packages is illustrated with a Collatz function example.

How can I sort numbers as though they were words?

Ruby's Array#sort will, by default, sort numbers like this, in order of their value:
[11, 12, 13, 112, 113, 124, 125, 127]
I'd like to sort an array of numbers like this, as though they were words being alphabetized:
[11, 112, 113, 12, 124, 125, 127, 13]
How can I do this? (Ultimately, I want to do this with Hash keys, so if you want to answer that way instead, that's fine.) Also, is there a name for this type of sort?
You are all crqzy ))) I have a such solution:
a.sort_by &:to_s
Well, one way is to convert all of the values to strings, then convert them back.
a = [11, 12, 13, 112, 113, 124, 125, 127]
a = a.map(&:to_s).sort.map(&:to_i)
p a # => [11, 112, 113, 12, 124, 125, 127, 13]
You can pass in a block to sort that accepts two arguments and returns the result of your own custom-defined comparison function. The example should speak for itself, but should you have any questions, feel free to ask.
a = [11, 112, 113, 12, 124, 125, 127, 13]
new_a = a.sort do |x,y|
"%{x}" <=> "%{y}"
end
puts new_a
A note: I suspect that the reason you're looking for this sort of solution is because the objects you want sorted are not Integers at heart. It might be worthwhile and semantically more pleasing to subclass Integer. Although it will obviously make instantiation harder, it feels more correct, at least to me.

Resources