C, 106
Golfed version
f(n){
for(int i,h=n*2<<n;h--;(i/3|i/3*2)-i||(putchar(i>>h%n&1?45:124),h%n||puts(h%(n*2)?"":"\n")))
i=h/2/n;
}
Original version
i,j,n;
main(){
scanf("%d",&n);
for(i=1<<n;i--;)if((i/3|i/3*2)==i){
for(j=1<<n;j/=2;)printf("%c",i&j?'-':'|');puts("");
for(j=1<<n;j/=2;)printf("%c",i&j?'-':'|');puts("\n");
}
}
How it works
The variable i
runs from 1<<n-1
down to 0, producing all possible binary numbers with n
digits. 0 encodes for |
and 1 encodes for -
. We are interested in numbers that contain 1's in pairs. Obviously such numbers are divisible by 3.
When a number is divided by 3, the original number can be recovered by multiplying the result by 2 and adding it to itself (effectively mutliplying by 3.) Most numbers will require a carry, but when the process is carried out on the numbers of interest, no carry is required, so in these cases only, OR can be used instead of addition. This is used to test for the numbers of interest, as they are the only ones where the expression i/3|i/3*2
returns the original value of i
. See example below.
1111
=15 ---> 0101
=5 ---> 1111
=15 (valid, 0101|1010
==0101+1010
)
1001
=9 ---> 0011
=3 ---> 0111
=7 (invalid, 0011|0110
!= 0011+0110
)
The test value is always equal or less than the original value. As numbers that are not multiples of 3 also return a number less than the original when divided by 3 then multipled by 3, the test gives the desired FALSE on these numbers too.
In the original version a couple of loops in j
are used to scan through the bits of i
and produce the output. In the golfed version a single for
loop is used, in which h
runs through all numbers from (n*2)*(1<<n)-1
down to 0. Values of i
are generated by h/2/n
. The variable j
is no longer used, as the equivalent quantity is obtained from h%n
. The use of n*2
enables both lines to be printed from the same loop, with some nifty multiplexing in the puts
statement to print either one or two newlines at the end of the row.
Note that the meat of this is in the increment position of the for()
bracket and therefore gets executed after the i=h/2/h
.
Sample output n=6:
$ ./a
6
------
------
----||
----||
--|--|
--|--|
--||--
--||--
--||||
--||||
|----|
|----|
|--|--
|--|--
|--|||
|--|||
||----
||----
||--||
||--||
|||--|
|||--|
||||--
||||--
||||||
||||||
——
and|
by length like Dennis's, not length-n
strings of—
and|
filtered by—
appearing in pairs. And for the latter, I'd expect it to be via regexes or string operations on the produced string, likes.split('——
)`, not by an arithmetic approach like yours. \$\endgroup\$