ListTricks 2.52

documentation notebook

Eric Rowland
https://ericrowland.github.io/packages.html

Introduction

ListTricks is a collection of about 50 structure manipulation, classification, and searching tools that can be thought of as extending the core Wolfram Language.
This introduction gets you started with a few features of the package; the next section provides a complete list of package symbols along with their usage messages and further examples.

To use ListTricks, first you will need to load the package by evaluating the following cell. (If you need help, see loading a package.)

<<ListTricks`

Structure manipulation

Most functions in ListTricks are for manipulating the structure of lists and arrays.  Several of these perform geometric operations on two-dimensional arrays; these include RotateClockwise, Shear, and Tile.

With[{array=CellularAutomaton[{6,2,(1/2)},{{1},0},127]},ArrayPlot/@{array,RotateClockwise[array],Shear[array],Tile[array,{400,400}]}]

Several ListTricks symbols provide new ways of extracting structural elements.  Portion lets you extract the first half, third, fourth, etc. of a list:

Alphabet[]

Portion[%,1/3]

Period extracts the repeating part of a list:

RealDigits[5/17,10,50]

Period[First[%]]

Mapping

ListTricks adds a few mapping functions.

MapAcross maps a list of functions onto a list of elements of the same length:

MapAcross[{IntegerQ,PrimeQ,EvenQ},{1.5,2,6}]

MapList maps a function onto each element of a list independently:

StringJoin/@MapList[Function[letter,FromCharacterCode[ToCharacterCode["z"]-(ToCharacterCode[letter]-ToCharacterCode["a"])]],Characters["example"]]

Classification

Part of manipulating objects is putting them in canonical form.  ListTricks contains several functions for this sort of operation.

FirstSortedRotation returns the rotation of a list that occurs first in a sorted listing of all rotations.

RandomInteger[{0,1},40]

FirstSortedRotation[%]

OrbitRepresentatives finds representatives of a list under the orbit of several functions.
Here we "mod out" by reversal and complementation, leaving a list of tuples that are distinct under these operations:

Tuples[{0,1},4]

OrbitRepresentatives[{Reverse,1-#&},%]

Searching

ListTricks also includes some functions for searching and selecting.

Occurrence is a generalization of FirstPosition; it returns the position of the nth match.

Occurrence[{1.2,π,2,3,(Sqrt[5])},_Integer,"not that many integers!",2]

Sift repeatedly generates a random object until it finds one satisfying a certain condition.

Sift[RandomInteger[100000],Length[FactorInteger[#]]==2&]

FactorInteger[%]

Examples searches through a range of values specified like Table, identifying examples of a claim.
It is similar to Select, but instead of requiring you to generate all candidates before testing, it generates them one at a time (using Do).  This is useful for large searches.

Examples[Total[IntegerDigits[n]]==37,{n,0,50000}]

Presentation

Often it’s useful to format data for visualization.  ColumnWrap and MulticolumnArrayPlot break up multi-row arrays into several shorter arrays.

ColumnWrap[{{1,2},{2,4},{3,8},{4,16},{5,32}}]

MulticolumnArrayPlot[Table[IntegerDigits[n,2,6],{n,0,(2^6)-1}],PixelConstrained->4]

IndentedExport exports data with indentation to show the structure:

IndentedExport["temp.m",{"California"->{"Abbreviation"->"CA","Capital"->(Entity["Sacramento", Entity["City",{"Sacramento","California","UnitedStates"}], "Entity[\"City\", {\"Sacramento\", \"California\", \"UnitedStates\"}]", "city"])},"Nevada"->{"Abbreviation"->"NV","Capital"->(Entity["Carson City", Entity["City",{"Carson","Nevada","UnitedStates"}], "Entity[\"City\", {\"Carson\", \"Nevada\", \"UnitedStates\"}]", "city"])}}];
Import["temp.m","Text"]
DeleteFile["temp.m"]

Package symbols

Accrete (a generalization of Accumulate)

?Accrete

Accrete[Range[10]]

Accrete[Range[10],Plus]

Accrete[Range[10],Times]

Accrete[Range[10],LCM]

Accrete[Range[10],List]

Accrete[List/@Range[10],Join]

data=RandomSample[Range[10]]

Accrete[data,Max]

Clear[data]

Accrete[Range[10],f]

Accrete[Range[10],Sequence]

AgreementLength

?AgreementLength

AgreementLength[{a,b,c,d},{a,b,c,e}]

AgreementLength[IntegerDigits[1072934],IntegerDigits[1072]]

ArrayMap

?ArrayMap

Grid[Table[Binomial[n,m],{n,0,5},{m,0,5}]]

In a two-dimensional array, level 2 corresponds to columns.

Grid[ArrayMap[RotateLeftTo,Table[Binomial[n,m],{n,0,5},{m,0,5}],{2}]]

Grid[With[{d=2},ArrayMap[Most,Apply[(Subscript[a, ##1])&,Outer[List,Sequence@@Table[Range[0,2],{d}]],{d}],{2},1]]]

Grid[With[{d=2},ArrayMap[Most,Apply[(Subscript[a, ##1])&,Outer[List,Sequence@@Table[Range[0,2],{d}]],{d}],{2},2]]]

The fourth argument is the dimension affected by ArrayMap.

With[{d=6},(Dimensions[ArrayMap[Most,Outer[a,Sequence@@Table[Range[0,1],{d}]],{d},#1]]&)/@Range[d]]

With[{d=6},(Dimensions[ArrayMap[{}&,Outer[a,Sequence@@Table[Range[0,1],{d}]],{d},#1]]&)/@Range[d]]

Some ArrayMap functionality can be achieved by MapThread:

Grid[ArrayMap[RotateLeftTo,Table[Binomial[n,m],{n,0,5},{m,0,5}],{2}]]
Grid[MapThread[RotateLeftTo[{##}]&,Table[Binomial[n,m],{n,0,5},{m,0,5}]]]

ColumnMap (a variant of MapThread)

?ColumnMap

ColumnMap[f,{{a,b},{c,d},{e,f,g}}]

Interpolate a polynomial down each column of Pascal's triangle:

Portion[ColumnMap[Factor[InterpolatingPolynomial[#1,n-#2]]&,Table[Binomial[n,m],{n,10},{m,n}]],(1/2)]

Here is a ragged array:

array=UnpadRight/@Shear[PadRight[Table[Mod[Binomial[n,m],2],{n,10},{m,n}]],-1,3];
Grid[array]

ColumnMap fills in the holes with Null by default.

ColumnMap[f,array]

Replacing each 0 with Null causes these entries to be treated as background.
For empty columns, the second argument to f is the index of the first nonexistent row.

ColumnMap[f,array/.0->Null]

Use the DefaultElement option to change the default element.

ColumnMap[f,array,DefaultElement->0]

Clear[array]

ColumnWrap (a generalization of Multicolumn)

?ColumnWrap

This table would be very long without wrapping the columns.

ColumnWrap[Table[{n,DigitCount[n,2,1]},{n,100}],11]

Dynamically change the number of super-columns:

Manipulate[ColumnWrap[Table[{n,DigitCount[n,2,1]},{n,100}],n],{{n,10,"columns"},1,14,1}]

Complements

?Complements

Complements gives information about the symmetric difference, and it keeps track of which list each element came from.

Complements[Range[1,10],Range[3,12]]

Manipulate[Complements@@Table[Range[i,i+m],{i,1,100,n}],{{m,3},1,10,1},{{n,9},1,10,1}]

Examples and Counterexamples

?Examples

Find primes:

Examples[PrimeQ[n],{n,10}]

Stop when the first example is found:

Examples[Boole[Outer[CoprimeQ,x+{-1,0,1},y+{-1,0,1}]]=={{0,0,0},{0,1,0},{0,0,0}},{x,100},{y,100},1]

?Counterexamples

Verify that all integers in the range 1≤n≤10 are positive:

Counterexamples[n>0,{n,1,10}]

Counterexamples[PrimeQ[n],{n,10}]

FirstSortedElement

?FirstSortedElement

letters=RandomChoice[Alphabet[],10]

FirstSortedElement[letters]

Clear[letters]

FirstSortedElement does not sort the entire list, so it is faster than using First[Sort[ ]]:

list=RandomInteger[(10^10),10000];

AbsoluteTiming[Do[First[Sort[list]],{1000}]]

AbsoluteTiming[Do[FirstSortedElement[list],{1000}]]

Clear[list]

FirstSortedRotation

?FirstSortedRotation

FirstSortedRotation[{g,b,d,f,a,c,e}]

RandomInteger[1,100]

FirstSortedRotation[%]

FirstSortedRotation effectively gives the orbit representative of a list under RotateRight:

FirstSortedRotation[{g,b,d,f,a,c,e}]
First[OrbitRepresentatives[RotateRight,{{g,b,d,f,a,c,e}}]]

FixedPointPeriod

?FixedPointPeriod

FixedPointPeriod[Reverse,Range[5]]

FixedPointPeriod[I #&,1]

IndentedExport

?IndentedExport

IndentedExport is particularly useful for formatting lists of rules.

Table[i->Table[j->RandomInteger[10],{j,2}],{i,5}]

file=IndentedExport[FileNameJoin[{$TemporaryDirectory,"rules.m"}],%]

Import[file,"Text"]

DeleteFile[file]

Clear[file]

InExpression (a variant of InString)

?InExpression

Grab the last input expression:

2+2

InExpression[]

InString can also be used, but the result is a string and requires slightly more work to evaluate:

InString[-2]
MakeExpression@@ToExpression[%,InputForm,Hold]

Here is a more complex expression:

(Overscript[a, n+1])+(a^(n+2))+(Subscript[a, n+3])+(Underscript[a, n+4])

The output of InString is more difficult to read than the output of InExpression:

InString[]

InExpression[-2]

IntegerCompositions

?IntegerCompositions

IntegerCompositions[5]

IntegerPartitions gives the (reverse) sorted integer compositions:

IntegerPartitions[5]
%==DeleteDuplicates[ReverseSort/@IntegerCompositions[5]]

MapAcross

?MapAcross

MapAcross[{f,g,h},{a,b,c}]

MapList

?MapList

MapList[#+1&,Range[4]]

MapList[Append[#1,0]&,List/@Range[4]]

MatchLength

?MatchLength

MatchLength[{1,2,a,b},_Integer]

MulticolumnArrayPlot

?MulticolumnArrayPlot

ArrayPlot[CellularAutomaton[{39780,2,{{0},{1},{2},{3}}},{{1},0},(2^11)]]

Wrap the long evolution into columns:

MulticolumnArrayPlot[CellularAutomaton[{39780,2,{{0},{1},{2},{3}}},{{1},0},(2^12)],4,(2^8),Frame->False]

MultiRiffle (a generalization of Riffle)

?MultiRiffle

MultiRiffle[{1,2,3},{a,b,c},{E,π,I}]

MultiRiffle[{1,2,3},{a,b,c},{E,π,I},{z}]

MultirowArrayPlot

?MultirowArrayPlot

This plot is too wide to see much:

ArrayPlot[Partition[IntegerExponent[Range[(2^12)],2],(2^10)]]

Wrap it into multiple rows:

MultirowArrayPlot[Partition[IntegerExponent[Range[(2^12)],2],(2^10)],8]

MultisetComplement

?MultisetComplement

MultisetComplement[{a,b,b,b,c,c},{a,a,b,b,c}]

Multisets (a variant of Subsets)

?Multisets

Multisets[{a,b,c},3]

Multisets[Range[0,4],{2}]

Subsets produces increasing tuples:

Subsets[Range[8],{3}]

Subsets[Range[8],{3}]==Select[Tuples[Range[8],3],Less@@#1&]

Multisets produces nondecreasing tuples:

Multisets[Range[8],{3}]

Multisets[Range[8],{3}]==Select[Tuples[Range[8],3],LessEqual@@#1&]

NextTuple

?NextTuple

NextTuple[{a,a,a},{a,b,c,d}]

NextTuple[{a,d,d},{a,b,c,d}]

NextTuple[{3,1,5,1,2,2,4,5},Range[5]]

NextTuple[{3,1,5,1,2,2,4,5},{4,2,1,5,3}]

Count in binary:

NestList[NextTuple[#,{0,1}]&,{0,0,0,0},(2^4)-1]

FromDigits[#,2]&/@%

Count down in binary;

FromDigits[#,2]&/@NestList[NextTuple[#,{1,0}]&,{1,1,1,1},(2^4)-1]

Find the next tuple in a mixed base:

NextTuple[{c,0,π},{{a,b,c,d},{-1,0,1},{E,π}}]

Occurrence (a variant of FirstPosition)

?Occurrence

Occurrence[{a,b,c,π,7},_?NumericQ]

Occurrence[{a,b,c},_?NumericQ]

Find the tenth occurrence of 3 in the digits of π.

Occurrence[First[RealDigits[N[Pi,100]]],3,Missing["NotFound"],10]

Occurrence[First[RealDigits[N[Pi,100]]],3->FactorInteger,Missing["NotFound"],10]

Occurrence[{1,2,3,1,2,3,1,2,3,1,2,3},1,Missing["NotFound"],-2]

Occurrence only looks for elements on level {1}:

Occurrence[{{a,b},{c,d}},a]

Only

?Only

Only[{}]
Only[{1}]
Only[{1,2}]

Only[{},foo]
Only[{1},foo]
Only[{1,2},foo]

Orbit (a generalization of FixedPointList)

?Orbit

An orbit of the 3n+1 map:

Orbit[If[EvenQ[#],#/2,3#+1]&,40]

For the orbit of a single function that ends in a periodic point, Orbit is similar to FixedPointList:

Orbit[1+Floor[#/2]&,1000]

FixedPointList[1+Floor[#/2]&,1000]

Compute the orbit of a string under two functions:

Orbit[{StringReverse,StringReplace[#,{"a"->"b","b"->"a"}]&},"aaba"]

OrbitRepresentatives

?OrbitRepresentatives

OrbitRepresentatives is useful for “modding out” a list of objects by some symmetries.

Find representatives of the equivalence classes of length-4 binary lists under rotation:

OrbitRepresentatives[RotateRight,Tuples[{0,1},4]]

Find representatives under rotation and complementation:

OrbitRepresentatives[{RotateRight,1-#&},Tuples[{0,1},4]]

Find a representative of a string under reversal and interchange of letters:

OrbitRepresentatives[{StringReverse,StringReplace[#,{"a"->"b","b"->"a"}]&},{"babb"}]

Representatives under one operation and then another is in general not the same as representatives under both:

OrbitRepresentatives[1-#&,OrbitRepresentatives[RotateRight,Tuples[{0,1},4]]]

If the list is not closed under the functions, then it's possible to get elements that aren't in the original list:

OrbitRepresentatives[-#&,{0,1}]

If some elements in an orbit aren’t reachable from others, it’s possible to get duplicate representatives:

OrbitRepresentatives[If[EvenQ[#],#/2,3#+1]&,{1,8}]

If such elements appear sorted in the list, then the representatives will not be duplicated:

OrbitRepresentatives[If[EvenQ[#],#/2,3#+1]&,{8,1}]

OrbitRepresentatives only handles finite orbits:

TimeConstrained[OrbitRepresentatives[#+1&,{0}],1]

ParallelSelect

?ParallelSelect

ParallelSelect[Range[10],PrimeQ]

ParallelSelect is implemented using ParallelCombine:

ParallelCombine[Select[PrimeQ],Range[10]]

PartitionAfter and PartitionBefore

?PartitionAfter

PartitionAfter[IntegerDigits[10!,2],0]

?PartitionBefore

PartitionBefore[IntegerDigits[10!,2],0]

PartitionAt

?PartitionAt

PartitionAt[{a,b,c,d,e,f,g},{2,4}]

PartitionAt[{a,b,c,d,e,f,g},2]

PartitionAt[{a,b,c,d,e,f,g},{0,4,4,5,7,7}]

Total/@PartitionAt[Range[0,(2^7)-1],(2^(Range[6]))]

Table[(2^(n-3)) (3 (2^n)-2),{n,10}]

Period and PeriodLength

?Period

Period[{a,b,c,a,b,c,a,b}]

Period[{1,1,1,1}]

Period[list] is equivalent to FindRepeat[list], but Period issues a warning if the period does not occur at least twice:

FindRepeat[{a,b,a}]

Period[{a,b,a}]

?PeriodLength

PeriodLength[{a,b,c,a,b,c,a,b}]

PeriodLength[{1,1,1,1}]

PeriodLength[{1,1,2,1,1}]

Find the period of digits in the binary representation of 1/163:

Period[Most[First[RealDigits[N[(1/163),100],2]]]]

Length[%]

Portion

?Portion

Portion[Range[11]]

Portion[Range[11],(1/2)]

Portion[Range[11],(1/2),2]

Portion[Range[11],(2/3)]

Extract the middle third of a list:

Portion[Range[100],(1/3),2]

Extract the final two thirds of a list:

Portion[Range[100],(1/3),{2,3}]

A list is always partitioned by its portions:

And@@Flatten[Table[Range[r]==Join@@Table[Portion[Range[r],(1/n),i],{i,n}],{r,20},{n,10}]]

RaggedArrayDepth

?RaggedArrayDepth

This expression is a list of lists of lists:

RaggedArrayDepth[{{{a,b},{c,d,e}},{{f},{g,h},{i}}}]

This expression is a list but not a list of lists:

RaggedArrayDepth[{{a,b},c}]

For full arrays, RaggedArrayDepth agrees with ArrayDepth.

RaggedArrayDepth[{{a,b,c},{d,e,f}}]

ArrayDepth[{{a,b,c},{d,e,f}}]

RationalRange

?RationalRange

List all rational numbers in the interval from 2 to 3 with denominator at most 10:

RationalRange[2,3,10]

RationalRange[2,3,{7,9,2}]

Find rational approximations of π with small denominators:

RationalRange[π-(1/100),π+(1/100),20]

ReverseAll

?ReverseAll

With[{expr=a[b[c,d],e[f[g,h,i],j[]]]},{TreeForm[expr],TreeForm[ReverseAll[expr]]}]

RotateClockwise and RotateCounterClockwise

?RotateClockwise

?RotateCounterClockwise

Grid[{{a,b,c,d},{e,f,g,h},{i,j,k,l}}]

Grid[RotateClockwise[{{a,b,c,d},{e,f,g,h},{i,j,k,l}}]]

Grid[RotateClockwise[{{a,b,c,d},{e,f,g,h},{i,j,k,l}},2]]

Grid[RotateCounterClockwise[{{a,b,c,d},{e,f,g,h},{i,j,k,l}}]]

RotateLeftTo and RotateRightTo

?RotateLeftTo

RotateLeftTo[{1.2,π,2,3,(Sqrt[5])},_Integer]

RotateLeftTo[{0,1,0,2,0,0}]

?RotateRightTo

RotateRightTo[{1.2,π,2,3,(Sqrt[5])},_Integer]

RotateRightTo[{0,1,0,2,0,0}]

Second

?Second

Second[{a,b,c}]

Second[a^2+b^2]

Second[{}]

Second[{},"none"]

Shear

?Shear

Grid[Shear[Table[Range[10],{10}]]]

Grid[Shear[Table[Range[10],{10}],(1/2)]]

Grid[Shear[Table[Range[10],{10}],2,3]]

Use the option Axis to specify a subarray that is to remain in its original rotation.
Possible values are Top, Center, Bottom, or the position of the subarray.

Grid[Shear[Table[Range[10],{10}],3,Axis->5]]

ArrayPlot[Shear[CellularAutomaton[30,{{1},0},100],Axis->Bottom],ImageSize->200]

ArrayPlot[Shear[CellularAutomaton[30,{{1},0},100],-1,Axis->Bottom],ImageSize->200]

ArrayPlot[Shear[PadLeft[IntegerDigits[(3^(Range[0,255])),2]],Log[2,3],1],Frame->None,PixelConstrained->1]

MatrixForm/@Partition[Partition[Range[(3^3)],3],3]

MatrixForm/@Shear[Partition[Partition[Range[(3^3)],3],3],{1,2}]

A pyramid and a sheared pyramid:

With[{pyramid=CellularAutomaton[{1022,{2,1},{1,1}},{{{1}},0},10]},{Graphics3D[Cuboid/@({#3,#2,-#1}&)@@@Position[pyramid,1]],Graphics3D[Cuboid/@({#3,#2,-#1}&)@@@Position[Shear[pyramid,{-1,1},Axis->Bottom],1]]}]

Sift

?Sift

Produce random primes that are congruent to 2 mod 3:

Sift[RandomPrime[100],Mod[#,3]==2&,20]

?Distinct

Ensure that they are distinct:

Sift[RandomPrime[100],Mod[#,3]==2&,10,Distinct->True]

SuccessiveMaxima and SuccessiveMinima

?SuccessiveMaxima

?SuccessiveMinima

data=RandomSample[Range[10000]];

SuccessiveMaxima[data]

SuccessiveMinima[data]

ListLogPlot[{%,%%},Joined->True]

Clear[data]

Find tuples with successively maximal sums.

SuccessiveMaxima[Tuples[Range[0,3],4],Total]

Swap (a special case of SubsetMap)

?Swap

Swap[{a,b,c,d},{2,3}]

Swap[{a,b,c,d,e},{2,3,5}]

Swap[{a,b,c,d,e},{2,3,5},{4,2}]

Swap[{a,b,c,d,e},{1,2,1,3,1,4,1,5,1}]

Swap[{a,b,c,d,e},{1,2,1},{1,3,1},{1,4,1},{1,5,1}]

Swap entries in a nested list:

Swap[{{a,b},{c,d}},{{1,1},{2,2}}]

TakeAfter, TakeBefore, DropAfter, and DropBefore

?TakeAfter

TakeAfter[{1.2,π,2,3,(Sqrt[5])},_Integer]

TakeAfter[{1.2,π,2,3,(Sqrt[5])},_Integer,-1]

?TakeBefore

TakeBefore[{1.2,π,2,3,(Sqrt[5])},_Integer]

TakeBefore[{1.2,π,2,3,(Sqrt[5])},_Integer,-1]

?DropAfter

DropAfter[{1.2,π,2,3,(Sqrt[5])},_Integer]

DropAfter[{1.2,π,2,3,(Sqrt[5])},_Integer,-1]

?DropBefore

DropBefore[{1.2,π,2,3,(Sqrt[5])},_Integer]

DropBefore[{1.2,π,2,3,(Sqrt[5])},_Integer,-1]

Tile

?Tile

Tile[Range[5],13]

Grid[Tile[{{1,2,3},{4,5,6}},{7,7}]]

ArrayPlot[Tile[{{1,0,1},{0,1,0}},{100,100}]]

Partition[Partition[Range[12],2],3]

Graphics3D[{MapIndexed[Text[##1]&,Tile[{{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}},{5,5,5}],{3}]},Boxed->False]

Table[Length[Tile[Range[5],i]],{i,20}]

Trim

?Trim

ConstantArray[#,#]&/@Range[5,10]

Trim[%]

In order to use Transpose, all rows must be of the same length.

(Take[Range[50],{#2+1,-1,2^#1}]&)@@@{{0,0},{2,0},{3,0}}

Length/@%

Transpose[Trim[%%]]

Trim a multidimensional array:

Trim[{{{a,b},{c,d,e}},{{f},{g,h},{i}}}]

Trim[{{{a,b},{c,d,e}},{{f},{g,h},{i}}},{1}]

Trim[{{{a,b},{c,d,e}},{{f},{g,h},{i}}},{2}]

UnpadLeft, UnpadRight, and Unpad

?UnpadLeft

?UnpadRight

UnpadLeft[{0,0,0,1,0,1,0}]

UnpadLeft[{1,2,3,a,b,4,c,5,6},_Integer]

?Unpad

Unpad[{0,0,0,1,0,1,0}]

Unpad[{1,2,3,a,b,4,c,5,6},_Integer]

This cellular automaton has a lot of white space on the right:

ArrayPlot[CellularAutomaton[106,{{1,1},0},{(2^7)-1,All}],ImageSize->250]

Get rid of the white space:

ArrayPlot[UnpadRight[CellularAutomaton[106,{{1,1},0},{(2^7)-1,All}]],ImageSize->250]

Shear it and get rid of the white space on both sides:

ArrayPlot[Unpad[Shear[CellularAutomaton[106,{{1,1},0},{(2^7)-1,All}]]],ImageSize->50]

Control the level at which the unpadding is done:

UnpadLeft[{{1,1,1},{2,2,2},{3,4,5},{3,3,3},{10,11,12}},{a_ ..},{1}]

Unriffle

?Unriffle

Unriffle[{1,10,2,9,3,8,4,7,5,6,6,5,7,4,8,3,9,2,10,1}]

Unriffle[Range[20],7]

Unriffle is the inverse of MultiRiffle.

MultiRiffle@@Unriffle[Range[20],7]

$UserCloudDirectory

?$UserCloudDirectory

SystemOpen[$UserCloudDirectory]