Clever Little Programs

EvaluateAt


The function in the next cell takes an expression and a list of positions,
and evaluates in place the parts at the specified positions. This is taken
verbatim from "further examples" for ReplacePart in the Help Browser.

EvaluateAt[expr_, positions_] := Fold[ReplacePart[#1, Part[#1, Sequence @@ #2], #2] &, expr, positions]

In this case, {1,2} specifies the second element of the held list, and {1,-1,1} the first part of the last element.

EvaluateAt[HoldForm[{2 + 3, 3 + 4, 2 * 4 + 5}], {{1, 2}, {1, -1, 1}}]

{2 + 3, 7, 8 + 5}

Evaluate Pattern

The function below evaluates all parts of a held expression that match a  certain pattern. This is based on some code Robby Villegas of Wolfram  Research discussed at the 1999 Developer Converence.  See "Working With  Unevaluated Expressions" posted at
http://library.wolfram.com/conferences/devconf99/#programming.
At that conference Micheal Trott and Adam Strzebonski of Wolfram  Research are mentioned as the inventors of this trick : see  "Trott-Strzebonski method for In-Place Evaluation".

   EvaluatePattern[expr_, pattn_] := expr/.Pattern[p, pattn] :> With[{eval = p}, eval /; True]

The next cell creates a held expression and evaluates all sub expressions  with the Head Plus but nothing else evaluates. In this example  Erf[∞]+5, 1+3, 5+4, 36^(1/2) - 16^(1/2) evaluate to 6, 4, 9, 2 respectively since they each have the head Plus.

demo = HoldForm[(Erf[∞] + 5) Sin[π/(1 + 3)] (5 + 4)^(1/2)/(36^(1/2) - 16^(1/2))] ; <br /> EvaluatePattern[demo, _Plus]

6/2 Sin[π/4] 9^(1/2)

ReplaceAll at subexpressions matching a pattern

PatternReplaceAll :: usage = "PatternReplaceAll[expr, pattern, \nrule] uses ReplaceAll to ... pr_, pattn_, SingleRule : (_Rule | _RuleDelayed)] := PatternReplaceAll[expr, pattn, {SingleRule}]


Comments about the code above:



(1)  (Reverse@Sort...) ensures the later positions in (posn) still apply even
after folding several times.



(2)  We can't let the replacements take effect until after Fold is done
because the

     position of things may change.  To solve that I use Hold@@{expr}.



(3)  I don't use (rules__?OptionQ) because OptionQ[n_Integer->n+2] returns
False.

     Instead I use  rules:(_Rule|_RuleDelayed).



Now some examples:

ex = b * Gamma[1 + a]^2 * Gamma[1 + b]/Gamma[2, 4 + 2b] * PolyGamma[2 * b] * (b + 2)^2 ;


Here we use the rule (b→bb) on all subexpressions with the head
Gamma.

PatternReplaceAll[ex, _Gamma, bbb]

(b (2 + b)^2 Gamma[1 + a]^2 Gamma[1 + bb] PolyGamma[0, 2 b])/Gamma[2, 4 + 2 bb]


Here we use the rule (n_Integer→n+2) on all subexpressions with the
head Gamma.

PatternReplaceAll[ex, _Gamma, n_Integern + 2]

(b (2 + b)^2 Gamma[3 + a]^2 Gamma[3 + b] PolyGamma[0, 2 b])/Gamma[4, 6 + 4 b]


Here we use both rules (b→bb, n_Integer→n+2) on all
subexpressions with the head Gamma.

PatternReplaceAll[ex, _Gamma, {bbb, n_Integern + 2}]

(b (2 + b)^2 Gamma[3 + a]^2 Gamma[3 + bb] PolyGamma[0, 2 b])/Gamma[4, 6 + 4 bb]

Making a periodic function


In the next cell I define a periodic function that's piecewize linear.  

This example would still work if I changed

f[x_?(Im[#]===0&)] := f[Mod[x,5]]   to simply

f[x_] := f[Mod[x,5]]   but by using the more complicated the definition (f)
is only used for real arguments.

ClearAll[f] ;  f[x_ ? (0≤#<5&)] := If[x<2, 3, x - 4] ;    f[x_ ? (Im[#] === 0&)] := f[Mod[x, 5]] ;    Plot[f[x], {x, 0, 13}] ;

[Graphics:../HTMLFiles/Tricks_Misc_17.gif]

However, Mathematica can't do things like Integrals or Fourier series on the function defined  above.  If you wanted to find several terms of the Fourier series of the  above function I recommend defining the function over the period (-2.5  ≤ x ≤ 2.5) using UnitStep functions as in the next  cell.  Of course the function isn't actually periodic this way, but the  function FourierTrigSeries doesn't care about that.

ClearAll[f] ;  f[x_] := (1 + x) UnitStep[x + 5/2] + (2 - x) UnitStep[x] + (-7 + x) UnitStep[x - 2] ;


Needs["Calculus`FourierTransform`"];

FourierTrigSeries[f[t], t, 4, FourierParameters→{0,5/2}]

5/2^(1/2) (39/(10 10^(1/2)) + 10^(1/2) ((2 - 15 π)/(50 π^2) - (-15 π - 2)/(50 & ... 60;^2) - (12 π - 1)/(225 π^2)) Sin[15 π t] - Sin[20 π t]/(10 10^(1/2) π))

In general you should find that Mathematica's full symbolic capabilities including Integrate, LaplaceTransform, etc.  can be used on piecewise continuous functions defined in terms of UnitsStep  functions. This isn't true for the programming style used earlier.

Take generalized

The #& notation is explained in the discussion of Function.

ClearAll["Global`*"] ;  TakeRepeated[ls_List, t_List] := First/@Rest[  F ... br />    a1 = {a, b, c, d, e, f, g, h, i, j, k, l, m} ;    TakeRepeated[a1, {2, 3, 4, 1}]

{{a, b}, {c, d, e}, {f, g, h, i}, {j}}


Portions of the function above are implemented below to illustrate how it
works.

tst = FoldList[Through[{Take, Drop}[#1[[2]], #2]] &, {{}, a1}, {2, 3, 4, 1}] ;    Do[Print[tst[[n]]   ], {n, 5}]

{{}, {a, b, c, d, e, f, g, h, i, j, k, l, m}}

{{a, b}, {c, d, e, f, g, h, i, j, k, l, m}}

{{c, d, e}, {f, g, h, i, j, k, l, m}}

{{f, g, h, i}, {j, k, l, m}}

{{j}, {k, l, m}}


The effects of FoldList and Through are hard to grasp.  The lines below
demonstrates what they do.

FoldList[f, x, {2, 3, 4, 1}]  //TableForm

x
f[x, 2]
f[f[x, 2], 3]
f[f[f[x, 2], 3], 4]
f[f[f[f[x, 2], 3], 4], 1]

ClearAll[f, g] ;    Through[(f + g)[x]]

f[x] + g[x]

Thread generalized

This was written by Carl Woll.

ClearAll["Global`*"] ;  WollThread[h_, args_List] :=       ... , a_/;a>=i]], i], {i, Length[args]}]        WollThread[Plus, {{a, b}, {c, d, e}, {f}}]

{a + c + f, b + d, e}

Flatten without evaluating subexpressions

This was written by Dave Wagner.

ClearAll["Global`*"] ;  Attributes[MyFlatten] = {HoldFirst} ;    MyFlatt ... p;  Hold[x__] :>Hold[{x}]         MyFlatten[{{Sqrt[4] + 3, x1}, {{x3}, x4}}]

Hold[{4^(1/2) + 3, x1, x3, x4}]

Preventing TrigExpand from expanding as far as it can


You may not want TrigExpand to go as far as possible in expanding the
trigonometric expression below.  Tom Burton prevents TrigExpand from
expanding the products by changing the Head Times, and then changing it back
to Times after using TrigExpand.

Clear["Global`*"] ;  expr = Sin[2π  ω  t + 2 π  δ] ;    TrigExpand[expr]

2 Cos[π δ] Cos[π t ω]^2 Sin[π δ] + 2 Cos[π δ]^2 Cos[&# ... 0; δ]^2 Sin[π t ω] - 2 Cos[π δ] Sin[π δ] Sin[π t ω]^2

TrigExpand[expr/.HoldPattern[Times[p__]] :>TimesHold[p]]/.      TimesHold[p__] :>Times[p]

Cos[2 π t ω] Sin[2 π δ] + Cos[2 π δ] Sin[2 π t ω]

Finding the Domain of a defined function


Suppose we have a function (f[_]) that is defined for certain arguments.

The Cells below include a  program designed to indicate the values where (f)
is defined.

ClearAll[f, Domain] ;  f[1] = Sin[1] ;    f[2] = Sin[2] ;    f[q_Rational] := Sin[Numerator[q]]    f[n_ ? Negative] := Sin[-n]

Definitions for (f) are stored in DownValues[f].

DownValues[f]

{HoldPattern[f[1]] Sin[1], HoldPattern[f[2]] Sin[2], HoldPattern[f[q_Rational]] Sin[Numerator[q]], HoldPattern[f[n_ ? Negative]] Sin[-n]}


A certain part of each DownValue indicates the type of argument for which (f)

is defined.  This operation is an important part of the function below which
gives the same

result without the Pattern matching notation.

Part[#, 1, 1, 1] &/@DownValues[f]

{1, 2, q_Rational, n_ ? Negative}

ClearAll[Domain] ;  Domain[func_] := Module[{temp, t0, t1, t2},    (temp = Part[#, ...         Join[t0, t1, t2])       ]


  

Now Domain[f] can be use to determine the values where (f) is defined.

Domain[f]

{1, 2, Rational, Negative}

Finding the constant term(s) in a sum

The short program below will find the constant term in a sum.  The #&  notation used here is explained in the discussion of Function.

ClearAll[ConstantTerm, x, a, b] ;  ConstantTerm[expr_ ? NumericQ] := expr ;  C ... 371;    ConstantTerm[expr_]/;MemberQ[Attributes[Evaluate[Head[expr]]], NumericFunction] = 0 ;


Below we see several examples where the constant term is found.  When the
expression has no constant term 0 is returned.

ConstantTerm[1/3 + x + Sqrt[2] + x y^2 + Pi + 3 /(1 + (y + 1)^(1/2))]

1/3 + 2^(1/2) + π

ConstantTerm[x + x y^2 - x^2]

0

ConstantTerm[π/(4 + π/2) x]

0

ConstantTerm[Sqrt[x] + 1/x + 5 + Sqrt[2]]

5 + 2^(1/2)


ConstantTerm isn't defined if it's given an argument that isn't a numeric
function.

ConstantTerm[a&&b]

ConstantTerm[a&&b]


An alternate definition for ConstantTerm with the same effect is given in the
next cell.

ClearAll[ConstantTerm] ;  ConstantTerm[poly_ ? PolynomialQ] :=       ... nbsp;     ]     },       ReplacePart[poly, 0, posn]   ]

KroneckerProduct of matrices

ClearAll["Global`*"] ;  KroneckerProduct[A_ ? MatrixQ, B_ ? MatrixQ] := > ... ;With[{tensor = Outer[Times, Transpose[A], B]},   Flatten[MapThread[Join, tensor, 2], 1]]

A = {{a11, a12}, {a21, a22}} ;    B = {{b11, b12}, {b21, b22}} ;    KroneckerProduct[A, B]//MatrixForm

( a11 b11   a11 b12   a12 b11   a12 b12 )            a11 b21   a11 b22   a12 b ...             a21 b11   a21 b12   a22 b11   a22 b12            a21 b21   a21 b22   a22 b21   a22 b22


InterpolatingFunction form for the solution to a system of equations.

Carl Woll gave the solution below on how to find Interpolating functions  that solve a set of equations.  
Suppose you are trying to find  Interpolating functions for y[t], x[t] that solve the equations
{ x[t]^2 + y[t]^2 == t^2  ,  y[t] == x[t]^2 }   for (t) between 0 and 1.

ClearAll[x, y, f, g, t] ;  f[t_] := x[t]^2 + y[t]^2 - t^2 ;  g[t_] := y[t] - x[t]^2 ;  eqs = {f '[t] == 0, g '[t] == 0, f[1] == 0, g[1] == 0}

{-2 t + 2 x[t] x^′[t] + 2 y[t] y^′[t] == 0, y^′[t] - 2 x[t] x^′[t] == 0, -1 + x[1]^2 + y[1]^2 == 0, y[1] - x[1]^2 == 0}

soln=NDSolve[eqs,{x,y},{t,0,1}]

{{xInterpolatingFunction[{{0., 1.}}, <>], yInterpolatingFunction[{{0., 1 ... nterpolatingFunction[{{0., 1.}}, <>], yInterpolatingFunction[{{0., 1.}}, <>]}}


x1=x/.soln[[1]];

y1=y/.soln[[1]];



Block[{$DisplayFunction=Identity},

    p1=Plot[Re[x1[t]],{t,0,1},PlotLabel->"Real Part of x"];

    p2=Plot[Im[x1[t]],{t,0,1},PlotLabel->"Imaginary Part of x"];

    p3=Plot[Re[y1[t]],{t,0,1},PlotLabel->"Real Part of y"];

    p4=Plot[Im[y1[t]],{t,0,1},PlotLabel->"Imaginary Part of y"];

    ];

Show[GraphicsArray[{{p1,p2},{p3,p4}},GraphicsSpacing ->
0.2,ImageSize->{550,380}]];

Making a list of integers relatively prime to n


Suppose we want to find a list of integers relatively prime to a Positive
Integer (n). An immediate candidate is the function in the next cell, but it
isn't very fast for large n because it has to examine each integer between 2
and (n-1).

ClearAll[RelativePrimes, pdLst, g] ;  RelativePrimes[n_Integer]/;n>2 := Select[Range[n - 1], GCD[#, n] === 1&]

RelativePrimes[400000] ;//Timing

{9.34 Second, Null}


Ranko Bojanic found a faster solution that uses the fact  that  k< n is
relatively prime to n if it is not divisible by any prime divisor of n. The
list of  prime divisors of n is obtained by the following function.

pdLst[n_] := First[Transpose[FactorInteger[n]]]

The definition for (pdList) in the next cell is faster, but it doesn't  work in Version 3 or earlier. I am sort of splitting hairs here because an  expression has to be quite large for Part[expr, All, 1] to be significantly  faster, and FactorInteger will seldom return a list with more than 10^6 factors.

pdLst[n_] := Part[FactorInteger[n], All, 1]


If (d) is a prime divisor of (n), then a list of integers between 2 and (n-1)
which are not divisible by n is given by the following line.

g[n_Integer, d_Integer] := Complement[Range[2, n - 1], d Range[n / d]]


We have to take all these lists, for all prime divisors of n, and their
intersection will be the list of all integers between 2 and (n-1) which are
relatively prime to n.  It is now easy to see that the list of relative prime
integers of n can be found from the following function.

ClearAll[RelativePrimes] ;  RelativePrimes[n_Integer]/;n>2 := Module[{g = C ... pdLst = First[Transpose[FactorInteger[n]]]}, Apply[Intersection, Map[g, pdLst]] ]

RelativePrimes[42]

{5, 11, 13, 17, 19, 23, 25, 29, 31, 37, 41}

The solution in the next cell is a slight variation of a program Alan  Hayes wrote and it's a little faster than the last program. Keep in mind this  variation doesn't work in Mathematica Version 3 or earlier because of the use of Part[expt, All, 1].

ClearAll[RelativePrimes] ;  RelativePrimes[n_Integer]/;n>2 := Fold[Complement[#, #2] &, Range[2, n - 1], Range[#, n - 1, #] &/@Part[FactorInteger[n], All, 1]]

How the above implementation of RelativePrimes works

An Algebraic Transformation


A user in the MathGroup wanted Mathematica to change

((-1+a) x-a y)\^2  into  ((a-1)x+a y)\^2

Allan Hayes gave the solution in the next cell.  This solution has to be
entered on a case by case basis.

Clear[a, x, y] ;  ((-1 + a) x - a y)^2/.(p_^n_ ? EvenQ) Collect[-p, x]^n

((1 - a) x + a y)^2

FactorRule in the next cell works and the rule doesn't need to know what  variables are involved.  The only disadvantage of FactorRule is that it's  more complicated than the first solution.  The use of (expr :) is discussed  in my section on Pattern.

FactorRule = expr : (__Plus)^(n_ ? EvenQ)  (Map[-#&, Part[expr, 1], 1]^n/.Times[-1, a_, b___]  -a * b) ;

((-1 + a) x - a y)^2/.FactorRule

((1 - a) x + a y)^2

A New Together

A user wrote to the MathGroup indicating that Together takes a very long  time with expressions that have on the order of 10^7 leaves. They noticed together expands the numerator of the result as in  the next example, and suspected time could be saved if the numerator wasn't  expanded.

ClearAll["Global`*"] ;  Together[(a + b)/(c + d) + (e + f)/(g + f)]

(c e + d e + a f + b f + c f + d f + a g + b g)/((c + d) (f + g))

expr = (a + b)/(c + d) + (e + f)/(g + f) ;


Allan Hayes wrote SimpleTogether below which doesn't expand the numerator.
Allan's code is given in the next cell and it's very fast and very slick.

SimpleTogether[expr_Plus] := ((Plus @@ (# List @@ expr))/#) &[Times @@ Union[Denominator/@List @@ expr]]    SimpleTogether[expr_] := expr


In the next cell we see that SimpleTogether doesn't expand the numerator of
the result.

SimpleTogether[(a + b)/(c + d) + (e + f)/(g + f)]

((c + d) (e + f) + (a + b) (f + g))/((c + d) (f + g))

Notice Allan's program uses Union which has a SameTest option.  Some  nuances of Union and it's option are discussed at:
http://support.wolfram.com/Kernel/Symbols/System/Union.html  where it says the default SameTest setting used by Union is stronger  than using Equal or SameQ! This is demonstrated in the next line.

lst = N[Pi, 18] {1, 1 + 10^(-20)} ;  Union[lst]

{3.14159265358979324, 3.14159265358979324}


Next Union returns only one of the numbers when SameQ is used for SameTest.

Union[lst, SameTest (SameQ[#1, #2] &)]

{3.14159265358979324}


Considering the lines above I think Alan's SimpleTogether function should use
Union with the option SameTest→(SameQ[{#1,#2}]&).  In some applications
something else might be needed.  With that in mind I wrote a version of
Allan's program that has a SameTest option. I also give SimpleTogether the
options Modulus and Trig which the built-in version has and I give it a usage
message. The only thing missing is the extension option which the built-in
version of Together does have.

ClearAll[SimpleTogether] ;  SimpleTogether :: usage = "SimpleTogether[exp ... ), SameTesttst]] ]       SimpleTogether[expr_, opts___ ? OptionQ] := expr

Next we see that SimpleTogether still works.

SimpleTogether[(a + b)/(c + d) + (e + f)/(g + f)]

((c + d) (e + f) + (a + b) (f + g))/((c + d) (f + g))


I don't demonstrate the options but the default settings are shown below.

Options[SimpleTogether]

{SameTest (#1 === #2&), Modulus0, TrigFalse}

Making a Tensor into a Matrix

Consider the tensor (t1) in the next cell.

Clear[t1] ;  t1 = {{{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, {{2, 2, 2}, {2, 2, 2}, {2, 2, 2 ... {{{3, 3, 3}, {3, 3, 3}, {3, 3, 3}}, {{4, 4, 4}, {4, 4, 4}, {4, 4, 4}}}} ;  MatrixForm[t1]

( ( 1   1   1 )   ( 2   2   2 ) )              ...   3                       4   4   4                      3   3   3                       4   4   4


A user in the MathGroup wanted to express this tensor as a matrix with
MatrixForm in the next cell. Visually  this is simple. However, the
complicated structure of a tensor makes it a challenge to write an elegant
program that makes the conversion.

( 1   1   1   2   2   2 )            1   1   1   2   2   2            1   1    ...            3   3   3   4   4   4            3   3   3   4   4   4            3   3   3   4   4   4


Allan Hayes provided the following two solutions in the MathGroup.

t2 = Apply[Join, Join @@ Transpose[t1, {1, 3, 2}], 1] ;  MatrixForm[t2]

( 1   1   1   2   2   2 )            1   1   1   2   2   2            1   1    ...            3   3   3   4   4   4            3   3   3   4   4   4            3   3   3   4   4   4

 t2 = Flatten[Map[Flatten, Transpose[t1, {1, 3, 2}], {2}], 1] ;  MatrixForm[t2]

( 1   1   1   2   2   2 )            1   1   1   2   2   2            1   1    ...            3   3   3   4   4   4            3   3   3   4   4   4            3   3   3   4   4   4


Now suppose you want to do the same thing on the higher rank tensor (t1)
below

m1 = {   { {{11, 11}, {11, 11}}, {{12, 12}, {12, 12}}}, { {{13, 13}, {13, 13}}, {{14, 14}, {14 ... , {{26, 26}, {26, 26}} }} ;   t1 = {{m1, m2}, {m3, m4}} ;  MatrixForm[t1]

( ( ( 11   11 )   ( 12   12 ) )   ( ...            22   22                                           25   25                       26   26


Mathematica Version 4 has a NestWhile function that comes in handy here. The
code in the next cell will merge together tensors of any rank.

t2 = NestWhile[Apply[Join, Join @@ Transpose[#, {1, 3, 2}], 1] &, t1, TensorRank[#] >2&] ;  MatrixForm[t2]

( 11   11   12   12   15   15   16   16 )            11   11   12   12   15    ...             21   21   22   22   25   25   26   26            21   21   22   22   25   25   26   26

Distribute - A slick application

Dr. John Erb sent a problem to the MathGroup.
He had several pieces of  plastic of different thickness and wanted elegant Mathematica code that would determine what thicknesses can be made by stacking  together one or more of the pieces of plastic.

Robby Villegas replied to  the MathGroup in   [mg3203] Re: array ordered, of 18 Feb 1996:
This problem  amounts to finding all subsets of the list of thicknesses T, and for each  subset adding up its elements. Any subset of T can be described by giving a  status to each of T's elements: absent or present (as noted in Jorma  Virtamo's solution). In terms of a contribution to the total thickness, the  ith element adds 0 if it is absent, or adds (ti) if it is present. Thus, if  you take the Cartesian product of these ordered pairs: {0, t1} x {0, t2} x .  . . x {0, tn} you get all possible combinations of plates, e.g. {t1, 0, 0,  t4, t5, ...}, and you can add the elements of each combination. 'Distribute'  is perfect for forming Cartesian products. .....
What follows is a slight  variation of Robby's solution.
First we get a list of thicknesses paired  with zero in s2.

s1 = {0.12, 0.34, 0.53, 0.53} ;  s2 = Thread[{0, s1}]

{{0, 0.12}, {0, 0.34}, {0, 0.53}, {0, 0.53}}


Next Distribute returns the cartesian product of all the ordered pairs.

lst = Distribute[s2, List, List]

{{0, 0, 0, 0}, {0, 0, 0, 0.53}, {0, 0, 0.53, 0}, {0, 0, 0.53, 0.53}, {0, 0.34, 0, 0}, {0, 0.34 ... 0.53}, {0.12, 0.34, 0, 0}, {0.12, 0.34, 0, 0.53}, {0.12, 0.34, 0.53, 0}, {0.12, 0.34, 0.53, 0.53}}


As Robby Villegas pointed out Distribute can take third and fourth arguments
which specify heads that should be used to replace the outer and inner heads
that were distributed. In this case we want the outer head to remain as List
and we want to add the sublists. Hence Distribute in the next line does the
job.

Distribute[s2, List, List, List, Plus]//Union

{0, 0.12, 0.34, 0.46, 0.53, 0.65, 0.87, 0.99, 1.06, 1.18, 1.4, 1.52}


Alternatively we can use the next cell to get lists of the form {{sum,
list},...} where 'sum' is the total of the elements in 'list', and Union has
removed elements with same sum, and sorted the list so the values of sum are
increasing.

q1 = Union[{Plus @@ #, #} &/@lst, SameTest-> (First[#1] === First[#2] &)]

{{0, {0, 0, 0, 0}}, {0.12, {0.12, 0, 0, 0}}, {0.34, {0, 0.34, 0, 0}}, {0.46, {0.12, 0.34, 0, 0 ... }}, {1.18, {0.12, 0, 0.53, 0.53}}, {1.4, {0, 0.34, 0.53, 0.53}}, {1.52, {0.12, 0.34, 0.53, 0.53}}}

Union without sorting

In June 2000 there was a long thread in the MathGroup and you can read  about the discussion at
http://library.wolfram.com/mathgroup/archive/2000/Jun/msg00115. html  on how to write an efficient function that does the same thing as Union  without sorting the elements. Many agree that the best way to do this is with  the following ingeniuos function written by Carl Woll.

ClearAll[DeleteRepititions] ;  DeleteRepititions[x_] := Module[{t}, t[n_] := (t[n] = Sequence[] ; n) ; t/@x]

DeleteRepititions is demonstrated below.

DeleteRepititions[ {3, 1, 1, 6, 3, 2, 1, 1, 8, 2, 6, 8} ]

{3, 1, 6, 2, 8}


Actually the version Carl Woll posted used Block where I use Module above.  
The function runs a bit faster when defined using Block, but then it gives
the wrong result in the following example.

DeleteRepititions[ {3, 1, 1, t[3], 3, 2, t[3], 1, 1, 8, 2, 6, 8} ]

{3, 1, t[3], 2, 8, 6}


Created by Mathematica  (May 17, 2004)