Xah Lee
2010-12-01 13:04:33 UTC
in lisp lang, often there's pure exercise posted about manipulating
lists.
here's a old Mathematica post that Google recently dig'd up and
notified me (apparantly, it means people's been reading that post)
http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/72a9cf0ac76e7698/1234f5dd46b5e58e?lnk=gst&q=villegas
i hope that in this post, if anything, it gives lispers some idea
about how Mathematica is similar to lisp, and if i may say so, how
Mathematica is some order of magnitude easier to do complex list
manipulation problems than lisps.
(me, being a Mathematica fan, like to say this. Of course, this does
not mean Mathematica is “better” for everything. But take what you
will.)
for list manipulation, i think langs that might be comparable to
Mathematica's capabilities are those so-called array programing langs.
(e.g. APL. see http://en.wikipedia.org/wiki/Array_programming )
when i first ventured into lisp in ~1999 (or any lang other than
Mathematica), i was naive and was rather surprised that in lisp, list
structure programing is not much done at all (in comparison to my
experiences with Mathematica) Then in around 2004, i was naively
surprised that even in Haskell, there's even no default data type of
nested list. (i was naive because i thought every functional lang
relies on arbitrarily nested list as its main data structure. But with
about 10 years of industrial programing experience now, i think hardly
any programing or lang relies on nested list as its main data
structure. At most, there's just 2 or 3 levels of nesting as in
matrices.)
the post is pasted in the following:
-----------------------------------------
From: Xah Y Lee <***@fhda.edu>
Date: Apr 7 1995, 11:00 pm
Subject: Summary:Ways to get Odd Columns&Rows of Matrix
To: comp.soft-sys.math.mathematica
This is a summary of Ways to get only odd rows and columns of a
matrix.
Problem: Suppose we have a mxn matrix. We want to cross out the even
rows
and columns, and get the remaining matrix. How to do that?
This is built-in in mma. The simplest way to do it is
Part[myMatrix,{1,3,5...},{1,3,5...}]. See section 3.7.2, p.651 of the
mma
book.
Below is a collection of various ways to write this program. Some of
them
are general that can work on matrices with more than 2 dimensions, and
user can choose odd only, even only, or generalized such as every
third
member in the tensor. Most others are included not as a practical
solution but
as programming examples.
These pieces of codes are contributed by various members of mathgroup.
I've taken the liberty to modify some of them to make this a coherent
summary.
------------
Clear[myList]
myList = Array[a,{10,18}];
------------
(*Using Part*)
(*From: Robert Villegas <***@wri.com>*)
(*From: Count Dracula <***@kelvin.seas.virginia.edu>*)
(*
In my opinion this is the best solution.
Use Map[Select[Range[#], OddQ] &, Dimensions[myMatrix]] to generate a
list {{1,3,5,..}, {1,3,5,7...}}, then feed it to Part to extract, like
this
Part[myMatrix, {1,3,5}, {1,3,5,7}].*)
*)
MatrixSieve1a[myMatrix_] :=
Part[myMatrix,
Sequence@@ Map[ Range[1, #, 2]&, Dimensions[myMatrix]]
]
MatrixSieve1b[myMatrix_, sel_:OddQ] :=
Part[myMatrix,
Sequence@@ Map[(Select[Range[#], sel] &) , Dimensions[myMatrix]]
]
------------
(*Using Table.*)
(*From: Lou Talman <***@talmanl.mscd.edu>*)
(*easiest to understand.*)
MatrixSieve2[myMatrix_] :=
Module[{i,j},
Table[ myMatrix[[i, j]],
{i, 1, Length[myMatrix], 2},
{j, 1, Length[***@myMatrix], 2}
]
]
------------
(*using Partition. *)
(*From: Xah Lee <***@compuserve.com>*)
(*
This one is hard to understand. It's not easy to generalize as well.
It
will not work if the matrix contain odd number of row or column, but
it's
got the potential to become the most elegant solution. It's the
fastest
among all.
*)
MatrixSieve3[myMatrix_] := Map[ First, Partition[myMatrix,{2,2}],
{2,3}]
------------
(*Recursively elimate the second term.*)
(*From: Tyler Perkins <***@colorado.edu>*)
(*
Define OddOnly[], that will get rid of the second element in a list.
This is repeated recursively in a nested way so that at the end only
the
odd terms of the list is left.
Map OddOnly to every level of myList.
*)
OddOnly[{first_, second_, rest___}] := Join[{first}, OddOnly[{rest}]];
OddOnly[singleExpr_] := singleExpr;
MatrixSieve4[myMatrix_] := MapAll[ OddOnly, myMatrix]
------------
(*using Array and Part*)
(*From: "L. Hannibal" <***@caesar.physik.uni-oldenburg.de>*)
MatrixSieve5[myMatrix_]:=
Array[
myMatrix[[2 #1 -1,2 #2-1]]&,
{Ceiling[Length[myMatrix]/2], Ceiling[***@First@myMatrix/
2]}
]
------------
(*using Pattern and ReplaceRepeated*)
(*From: Robert Zimmerman <***@zim.uoregon.edu>*)
(*This is not a general method, but included here as a extra example
of
programming techniques. It only works on matrices whos elements have
the
form head[x,y]. It works by first flatten myList, then replace
elements
with even index with 0, then eliminate the zeros in the list. Lastly,
Partition them into the correct form.
*)
Partition[
,3
]
------------
(* using Fold and Drop *)
(*From: bob Hanlon <***@pafosu2.hq.af.mil>*)
(*works on matrices with even number of terms.
Not a good example of coding.
The use of Fold, Transpose and Drop are too complex.
Slow as well.
*)
Transpose[
Fold[ Drop,
Transpose[
Fold[ Drop, myList,
-Array[List,***@myList/2]
]
],
-Array[List,***@First@myList/2]
]
]
------------
Xah Lee
lists.
here's a old Mathematica post that Google recently dig'd up and
notified me (apparantly, it means people's been reading that post)
http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/72a9cf0ac76e7698/1234f5dd46b5e58e?lnk=gst&q=villegas
i hope that in this post, if anything, it gives lispers some idea
about how Mathematica is similar to lisp, and if i may say so, how
Mathematica is some order of magnitude easier to do complex list
manipulation problems than lisps.
(me, being a Mathematica fan, like to say this. Of course, this does
not mean Mathematica is “better” for everything. But take what you
will.)
for list manipulation, i think langs that might be comparable to
Mathematica's capabilities are those so-called array programing langs.
(e.g. APL. see http://en.wikipedia.org/wiki/Array_programming )
when i first ventured into lisp in ~1999 (or any lang other than
Mathematica), i was naive and was rather surprised that in lisp, list
structure programing is not much done at all (in comparison to my
experiences with Mathematica) Then in around 2004, i was naively
surprised that even in Haskell, there's even no default data type of
nested list. (i was naive because i thought every functional lang
relies on arbitrarily nested list as its main data structure. But with
about 10 years of industrial programing experience now, i think hardly
any programing or lang relies on nested list as its main data
structure. At most, there's just 2 or 3 levels of nesting as in
matrices.)
the post is pasted in the following:
-----------------------------------------
From: Xah Y Lee <***@fhda.edu>
Date: Apr 7 1995, 11:00 pm
Subject: Summary:Ways to get Odd Columns&Rows of Matrix
To: comp.soft-sys.math.mathematica
This is a summary of Ways to get only odd rows and columns of a
matrix.
Problem: Suppose we have a mxn matrix. We want to cross out the even
rows
and columns, and get the remaining matrix. How to do that?
This is built-in in mma. The simplest way to do it is
Part[myMatrix,{1,3,5...},{1,3,5...}]. See section 3.7.2, p.651 of the
mma
book.
Below is a collection of various ways to write this program. Some of
them
are general that can work on matrices with more than 2 dimensions, and
user can choose odd only, even only, or generalized such as every
third
member in the tensor. Most others are included not as a practical
solution but
as programming examples.
These pieces of codes are contributed by various members of mathgroup.
I've taken the liberty to modify some of them to make this a coherent
summary.
------------
Clear[myList]
myList = Array[a,{10,18}];
------------
(*Using Part*)
(*From: Robert Villegas <***@wri.com>*)
(*From: Count Dracula <***@kelvin.seas.virginia.edu>*)
(*
In my opinion this is the best solution.
Use Map[Select[Range[#], OddQ] &, Dimensions[myMatrix]] to generate a
list {{1,3,5,..}, {1,3,5,7...}}, then feed it to Part to extract, like
this
Part[myMatrix, {1,3,5}, {1,3,5,7}].*)
*)
MatrixSieve1a[myMatrix_] :=
Part[myMatrix,
Sequence@@ Map[ Range[1, #, 2]&, Dimensions[myMatrix]]
]
MatrixSieve1b[myMatrix_, sel_:OddQ] :=
Part[myMatrix,
Sequence@@ Map[(Select[Range[#], sel] &) , Dimensions[myMatrix]]
]
------------
(*Using Table.*)
(*From: Lou Talman <***@talmanl.mscd.edu>*)
(*easiest to understand.*)
MatrixSieve2[myMatrix_] :=
Module[{i,j},
Table[ myMatrix[[i, j]],
{i, 1, Length[myMatrix], 2},
{j, 1, Length[***@myMatrix], 2}
]
]
------------
(*using Partition. *)
(*From: Xah Lee <***@compuserve.com>*)
(*
This one is hard to understand. It's not easy to generalize as well.
It
will not work if the matrix contain odd number of row or column, but
it's
got the potential to become the most elegant solution. It's the
fastest
among all.
*)
MatrixSieve3[myMatrix_] := Map[ First, Partition[myMatrix,{2,2}],
{2,3}]
------------
(*Recursively elimate the second term.*)
(*From: Tyler Perkins <***@colorado.edu>*)
(*
Define OddOnly[], that will get rid of the second element in a list.
This is repeated recursively in a nested way so that at the end only
the
odd terms of the list is left.
Map OddOnly to every level of myList.
*)
OddOnly[{first_, second_, rest___}] := Join[{first}, OddOnly[{rest}]];
OddOnly[singleExpr_] := singleExpr;
MatrixSieve4[myMatrix_] := MapAll[ OddOnly, myMatrix]
------------
(*using Array and Part*)
(*From: "L. Hannibal" <***@caesar.physik.uni-oldenburg.de>*)
MatrixSieve5[myMatrix_]:=
Array[
myMatrix[[2 #1 -1,2 #2-1]]&,
{Ceiling[Length[myMatrix]/2], Ceiling[***@First@myMatrix/
2]}
]
------------
(*using Pattern and ReplaceRepeated*)
(*From: Robert Zimmerman <***@zim.uoregon.edu>*)
(*This is not a general method, but included here as a extra example
of
programming techniques. It only works on matrices whos elements have
the
form head[x,y]. It works by first flatten myList, then replace
elements
with even index with 0, then eliminate the zeros in the list. Lastly,
Partition them into the correct form.
*)
Partition[
0}//.
{ head___ ,0, tail___ } :> {head, tail},3
]
------------
(* using Fold and Drop *)
(*From: bob Hanlon <***@pafosu2.hq.af.mil>*)
(*works on matrices with even number of terms.
Not a good example of coding.
The use of Fold, Transpose and Drop are too complex.
Slow as well.
*)
Transpose[
Fold[ Drop,
Transpose[
Fold[ Drop, myList,
-Array[List,***@myList/2]
]
],
-Array[List,***@First@myList/2]
]
]
------------
Xah Lee