Programming Contest Solutions Archive
Return-Path: <akur@indo.net.id>
Received: from server.indo.net.id ([202.159.34.10]) by sby.mega.net.id
          (Netscape Mail Server v1.1) with SMTP id AAA128
          for <yogy-n@sby.mega.net.id>; Thu, 3 Oct 1996 18:35:15 +0700
Received: from akur by server.indo.net.id (SMI-8.6/ED1-ID)
	id SAA13712; Thu, 3 Oct 1996 18:27:26 -0700
Date: Thu, 3 Oct 1996 18:27:26 -0700
Message-Id: <199610040127.SAA13712@server.indo.net.id>
X-Sender: akur@pop.jakarta.indo.net.id
X-Mailer: Windows Eudora Light Version 1.5.2
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
To: yogy-n@sby.mega.net.id
From: Andy Kurnia <akur@indo.net.id>
Subject: Subsets

I had no time to find and read the original Subsets problem, so I might miss
out some details (ie. using 0 instead of 1 or so).

Following is the rough algorithm I think I based my Internal00 and
Internal01 functions on:

Let's view the subsets as bits (as how they are stored internally in Set Of
0..31), so bit 0 (least significant bit, rightmost bit) is on if 1 is in the
set, etc. Assuming that there are 4 elements, we get 16 (= 1 shl 4) subsets:

  Dec = Bin  {Subset}
    0 = 0000 {}
    1 = 0001 {1}
    2 = 0010 {2}
    3 = 0011 {1,2}
    4 = 0100 {3}
    5 = 0101 {1,3}
    6 = 0110 {2,3}
    7 = 0111 {1,2,3}
    8 = 1000 {4}
    9 = 1001 {1,4}
   10 = 1010 {2,4}
   11 = 1011 {1,2,4}
   12 = 1100 {3,4}
   13 = 1101 {1,3,4}
   14 = 1110 {2,3,4}
   15 = 1111 {1,2,3,4}

Chronologically sorting the list, we get:

  Dec = Bin  {Subset}  Pattern
    0 = 0000 {}         0
    1 = 0001 {1}        1
    3 = 0011 {1,2}      2
    7 = 0111 {1,2,3}    3
   15 = 1111 {1,2,3,4}  4
   11 = 1011 {1,2,4}    5
    5 = 0101 {1,3}      6
   13 = 1101 {1,3,4}    7
    9 = 1001 {1,4}      8
    2 = 0010 {2}        9
    6 = 0110 {2,3}     10
   10 = 1010 {2,4}     11
   14 = 1110 {2,3,4}   12
    4 = 0100 {3}       13
   12 = 1100 {3,4}     14
    8 = 1000 {4}       15

Now examine the bits more closely. We have 16 subsets, so lets say S = 16.
Starting at the rightmost bit (remember that this stands for {1}) from top
to bottom, we have a 0, 8 1's, and 7 0's. Examining bit 1 (second rightmost
bit) of the patterns 1-8 (those who have {1}), we have a 0, 4 1's, and 3
0's. Getting further, we examine bit 2 of the patterns 2-5 (those who do
have {1,2}). We get a 0, 2 1's, and one 0. Let's examine bit 3 of patterns
3-4 (having {1,2,3}). We get a 0, one 1, and no 0.

The conclusion? If we have S subsets (where S is a whole even number), the
first one and the last (S/2 - 1) doesn't include the element, but the other
subsets (the second up to S/2) includes it. So we may split our S elements
into three parts: (1) The zero part (pattern 0), which is exactly ONE subset
and includes no further element, (2) the include part (patterns 1..S/2),
which is exactly S/2 subsets, includes the element we are currently
interested to, and may include more elements as if the part itself (1..S/2)
was processed from the root, and (3) the exclude part (patterns (S/2 +
1)..(S - 1)), which is exactly (S/2 - 1) subsets, excludes (does not
include) the element we are currently interested to, and may include more
elements as if the (S/2..(S - 1)) part was processed from the root.

Confused? My goal is achieved then.

Just kidding. Let's try a completely different method of understanding. The
above statement is indeed correct, but they aren't designed to be
immediately understood if read only once. So let's recapitulate what you
have read:

* LEVEL 1: Process(0..15)

Assume that we have four elements. Then we have (1 shl 4) subsets, or 16
subsets. So let's assume, at the first level, that S1 = 16. And also at the
first level we have nothing yet, or {}.

S1 = 16 may be divided into three part.

Part 1: The zero part, which is a single subset contains no other element
than what we have collected, or {}.

From this part we have 0 = {}.

Part 2: The include part, which are S/2 subsets containing the element we
are interested of, {1}, as the first element (remember that we are at the
first level). The remaining elements can be determined by going deeper and
processing the part.

This part gives us 1..8 = {1} + process(1..8).

Part 3: The exclude part, which are the remaining (S/2 - 1) subsets that
does not contain the element {1} but contains further elements, determined
by going deeper and processing (S/2..S) part.

This part gives us 9..15 = process(8..15), of course without {1}.

So level 1 gives us:

0 = {}
1..8 = {1} + process(1..8)
9..15 = process(8..15)

* LEVEL 2

0 = {} stays the way it was.
1..8 = {1} + process(1..8) gets processed as follows:
    1 =    {1} + {} = {1}
    2..5 = {1} + {2} + process(2..5) = {1,2} + process(2..5)
    6..8 = {1} + process(5..8)
9..15 = process(8..15) yields:
    8 = {} -> ignore! this never happens in real world, 8 gets processed above
    9..12 = {2} + process(9..12)
    13..15 = process(12..15)

* LEVEL 3

0 = {}, 1 = {1} stays.
2..5 = {1,2} + process(2..5) is:
    2 =    {1,2} + {} = {1,2}
    3..4 = {1,2} + {3} + process(3..4) = {1,2,3} + process(3..4)
    5 =    {1,2} + process(4..5)
6..8 = {1} + process(5..8) is:
    5 = {1} + {} -> ignore
    6..7 = {1} + {3} + process(6..7) = {1,3} + process(6..7)
    8 = {1} + process(7..8)
9..12 = {2} + process(9..12) is:
    9 = {2}
    10..11 = {2} + {3} + process(10..11) = {2,3} + process(10..11)
    12 = {2} + process(11..12)
13..15 = process(12..15) is:
    12 = {} -> ignore
    13..14 = {3} + process(13..14)
    15 = process(14..15)

* LEVEL 4 (at last!)

0 = {}, 1 = {1}, 2 = {1,2} stays so.
3..4 = {1,2,3} + process(3..4)
    3 = {1,2,3} + {} = {1,2,3}
    4 = {1,2,3} + {4} = {1,2,3,4} -> no further!! S5 = 1 is NOT even.
    no exclude part, already using zero part
5 = {1,2} + process(4..5)
    4 = {1,2} + {} -> ignore, as usual
    5 = {1,2} + {4} = {1,2,4}
6..7 = {1,3} + process(6..7)
    6 = {1,3}
    7 = {1,3,4}
8 = {1} + process(7..8)
    8 = {1,4}
9 = {2} stays unmodified.
10..11 = {2,3} + process(10..11)
    10 = {2,3}
    11 = {2,3,4}
12 = {2} + process(11..12)
    12 = {2,4}
13..14 = {3} + process(13..14)
    13 = {3}
    14 = {3,4}
15 = process(14..15)
    15 = {4}

So we get the chronological order!! To get subset #n, simply keep
subdividing 0..(1 shl x)-1 and entering the include/exclude part where n
belongs in the currently examined subrange until you get either to the zero
part or to the last element where Sx = 1.

To get the n from a subset, just keep subdividing the full range 0..(1 shl
x)-1, entering the corresponding subrange (include/exclude part) until you
get to the zero part or the last element. By then you should be examining
the subrange n..n, just get n from either the 'low' or 'high' argument.

Any questions? Please reply.



He got upset when I make fun of him for using chronologic
instead of lexicographic, then he sent me this mail :

Return-Path: <akur@indo.net.id>
Received: from server.indo.net.id ([202.159.34.10]) by sby.mega.net.id
          (Netscape Mail Server v1.1) with SMTP id AAA131
          for <yogy-n@sby.mega.net.id>; Mon, 7 Oct 1996 22:45:16 +0700
Received: from akur by server.indo.net.id (SMI-8.6/ED1-ID)
	id WAA04018; Mon, 7 Oct 1996 22:37:06 -0700
Date: Mon, 7 Oct 1996 22:37:06 -0700
Message-Id: <199610080537.WAA04018@server.indo.net.id>
X-Sender: akur@pop.jakarta.indo.net.id
X-Mailer: Windows Eudora Light Version 1.5.2
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
To: yogy-n@sby.mega.net.id
From: Andy Kurnia <akur@indo.net.id>
Subject: My solution

Add these lines in front of my e-mail.

I use the term CHRONOLOGIC for two reasons. One, I rarely use the word
LEXICOGRAPHIC and second, LEXICOGRAPHIC is defined as: CHRONOLOGICALly found 
in dictionaries... :)

Whatever you say, Andy... 



Yet he's not satisfied and sent me another mail :

Return-Path: <akur@indo.net.id>
Received: from server.indo.net.id ([202.159.34.10]) by sby.mega.net.id
          (Netscape Mail Server v1.1) with SMTP id AAA152
          for <yogy-n@sby.mega.net.id>; Tue, 8 Oct 1996 14:42:42 +0700
Received: from akur by server.indo.net.id (SMI-8.6/ED1-ID)
	id OAA01810; Tue, 8 Oct 1996 14:34:31 -0700
Date: Tue, 8 Oct 1996 14:34:31 -0700
Message-Id: <199610082134.OAA01810@server.indo.net.id>
X-Sender: akur@pop.jakarta.indo.net.id
X-Mailer: Windows Eudora Light Version 1.5.2
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
To: yogy-n@sby.mega.net.id
From: Andy Kurnia <akur@indo.net.id>
Subject: Re: My solution

Correction to: Add these lines in front of my e-mail.

I use the term CHRONOLOGIC for two reasons. One, I rarely use the word
LEXICOGRAPHIC and second, LEXICOGRAPHIC is defined as: CHRONOLOGICALly found
in dictionaries if you read it in the proper sequence (ie. from the first
entry to the last entry)... btw, Length('CHRONOLOGIC') <
Length('LEXICOGRAPHIC') :)

Can you believe this guy?