import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Random;
import java.util.Collection;
class NutsAndBolts {
/**
* Given a set of bolts and an equally large set of nuts,
* where for each bolt there is a exactly one fitting nut,
* this algorithm finds a corresponding nut for every bolt.
* We cannot compare the sizes of two bolts or two nuts,
* the only thing we can do is to tell whether the nut is
* too big for the bolt or too small.
*
* The algorithm runs in O(NlgN) time and
* requires O(N) additional space (to copy the contents of
* the `nuts` and `bolts` lists.
*/
static <T extends Comparable<T>> List<Pair<Nut<T>, Bolt<T>>>
pairNutsAndBolts(Collection<Nut<T>> nuts,
Collection<Bolt<T>> bolts) {
if (nuts.size() != bolts.size()) {
"Expected: same amount of nuts as bolts"
+ " Got: len(nuts) = %d, len(bolts) = %d",
nuts.size(), bolts.size()
));
}
List<Nut<T>> copyNuts = new ArrayList<>(nuts);
List<Bolt<T>> copyBolts = new ArrayList<>(bolts);
shuffle(copyNuts, random);
shuffle(copyBolts, random);
List<Pair<Nut<T>, Bolt<T>>> list =
new LinkedList<Pair<Nut<T>, Bolt<T>>>();
pairNutsAndBolts(list, copyNuts, copyBolts, 0, nuts.size());
return list;
}
private static <T extends Comparable<T>> void pairNutsAndBolts(
List<Pair<Nut<T>, Bolt<T>>> list,
List<Nut<T>> nuts, List<Bolt<T>> bolts, int lo, int hi) {
if (hi - lo == 1) {
list.add(new Pair<>(nuts.get(lo), bolts.get(lo)));
} else if (hi - lo > 1) {
int mid = partition(nuts, bolts.get(lo), lo, hi);
partition(bolts, nuts.get(mid), lo, hi);
list.add(new Pair<>(nuts.get(mid), bolts.get(mid)));
pairNutsAndBolts(list, nuts, bolts, lo, mid);
pairNutsAndBolts(list, nuts, bolts, mid + 1, hi);
}
}
private static <T extends Comparable<U>, U> int partition(
List<T> array, U pivot, int lo, int hi) {
for (int i = lo; i < hi; i++) {
if (array.get(i).compareTo(pivot) == 0) {
swap(array, lo, i);
break;
}
}
int iLeft = lo, iRight = hi;
do {
iLeft++;
while (iLeft < hi - 1
&& array.get(iLeft).compareTo(pivot) < 0) {
iLeft++;
}
iRight--;
while (iRight > lo
&& array.get(iRight).compareTo(pivot) > 0) {
iRight--;
}
if (iLeft < iRight) {
swap(array, iLeft, iRight);
}
}
while (iLeft < iRight);
swap(array, lo, iRight);
return iRight;
}
private static <T
> void shuffle
(List
<T
> array,
Random random
) { final int n = array.size();
for (int i = 0; i < n - 1; i++) {
swap(array, i, i + random.nextInt(n - i - 1) + 1);
}
}
private static <T> void swap(List<T> array, int i, int j) {
assert i >= 0 && j >= 0
&& i < array.size() && j < array.size();
T temp = array.get(i);
array.set(i, array.get(j));
array.set(j, temp);
}
static class Nut<T extends Comparable<T>>
implements Comparable<Bolt<T>> {
private T value;
public Nut(T value) {
this.value = value;
}
@Override
public int compareTo(Bolt<T> bolt) {
return this.value.compareTo(bolt.value);
}
@Override
return value.toString();
}
}
static class Bolt<T extends Comparable<T>>
implements Comparable<Nut<T>> {
T value;
public Bolt(T value) {
this.value = value;
}
@Override
public int compareTo(Nut<T> nut) {
return this.value.compareTo(nut.value);
}
@Override
return value.toString();
}
}
static class Pair<T, U> {
private T first;
private U second;
public Pair(T first, U second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public U getSecond() {
return second;
}
@Override
return String.
format("(%s, %s)", first, second
); }
}
public static void main
(String[] args
) { List<Nut<Integer>> nuts = new ArrayList<>();
List<Bolt<Integer>> bolts = new ArrayList<>();
for (int i = 0; i < 10; i++) {
nuts.add(new Nut<>(i));
bolts.add(new Bolt<>(9 - i));
}
for (Pair<Nut<Integer>, Bolt<Integer>> pair
: pairNutsAndBolts(nuts, bolts)) {
}
}
}
aW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLkxpbmtlZExpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLlJhbmRvbTsKaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uOwoKY2xhc3MgTnV0c0FuZEJvbHRzIHsKICAgIC8qKgogICAgICogR2l2ZW4gYSBzZXQgb2YgYm9sdHMgYW5kIGFuIGVxdWFsbHkgbGFyZ2Ugc2V0IG9mIG51dHMsCiAgICAgKiB3aGVyZSBmb3IgZWFjaCBib2x0IHRoZXJlIGlzIGEgZXhhY3RseSBvbmUgZml0dGluZyBudXQsCiAgICAgKiB0aGlzIGFsZ29yaXRobSBmaW5kcyBhIGNvcnJlc3BvbmRpbmcgbnV0IGZvciBldmVyeSBib2x0LgogICAgICogV2UgY2Fubm90IGNvbXBhcmUgdGhlIHNpemVzIG9mIHR3byBib2x0cyBvciB0d28gbnV0cywKICAgICAqIHRoZSBvbmx5IHRoaW5nIHdlIGNhbiBkbyBpcyB0byB0ZWxsIHdoZXRoZXIgdGhlIG51dCBpcwogICAgICogdG9vIGJpZyBmb3IgdGhlIGJvbHQgb3IgdG9vIHNtYWxsLgogICAgICoKICAgICAqIFRoZSBhbGdvcml0aG0gcnVucyBpbiBPKE5sZ04pIHRpbWUgYW5kCiAgICAgKiByZXF1aXJlcyBPKE4pIGFkZGl0aW9uYWwgc3BhY2UgKHRvIGNvcHkgdGhlIGNvbnRlbnRzIG9mCiAgICAgKiB0aGUgYG51dHNgIGFuZCBgYm9sdHNgIGxpc3RzLgogICAgICovCiAgICBzdGF0aWMgPFQgZXh0ZW5kcyBDb21wYXJhYmxlPFQ+PiBMaXN0PFBhaXI8TnV0PFQ+LCBCb2x0PFQ+Pj4KICAgICAgICAgICAgcGFpck51dHNBbmRCb2x0cyhDb2xsZWN0aW9uPE51dDxUPj4gbnV0cywKICAgICAgICAgICAgQ29sbGVjdGlvbjxCb2x0PFQ+PiBib2x0cykgewogICAgICAgIGlmIChudXRzLnNpemUoKSAhPSBib2x0cy5zaXplKCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihTdHJpbmcuZm9ybWF0KAogICAgICAgICAgICAgICAgIkV4cGVjdGVkOiBzYW1lIGFtb3VudCBvZiBudXRzIGFzIGJvbHRzIgogICAgICAgICAgICAgICAgKyAiIEdvdDogbGVuKG51dHMpID0gJWQsIGxlbihib2x0cykgPSAlZCIsCiAgICAgICAgICAgICAgICBudXRzLnNpemUoKSwgYm9sdHMuc2l6ZSgpCiAgICAgICAgICAgICkpOwogICAgICAgIH0KCiAgICAgICAgTGlzdDxOdXQ8VD4+IGNvcHlOdXRzID0gbmV3IEFycmF5TGlzdDw+KG51dHMpOwogICAgICAgIExpc3Q8Qm9sdDxUPj4gY29weUJvbHRzID0gbmV3IEFycmF5TGlzdDw+KGJvbHRzKTsKICAgICAgICAKICAgICAgICBSYW5kb20gcmFuZG9tID0gbmV3IFJhbmRvbSgpOwogICAgICAgIHNodWZmbGUoY29weU51dHMsIHJhbmRvbSk7CiAgICAgICAgc2h1ZmZsZShjb3B5Qm9sdHMsIHJhbmRvbSk7CgogICAgICAgIExpc3Q8UGFpcjxOdXQ8VD4sIEJvbHQ8VD4+PiBsaXN0ID0KICAgICAgICAgICAgbmV3IExpbmtlZExpc3Q8UGFpcjxOdXQ8VD4sIEJvbHQ8VD4+PigpOwogICAgICAgIHBhaXJOdXRzQW5kQm9sdHMobGlzdCwgY29weU51dHMsIGNvcHlCb2x0cywgMCwgbnV0cy5zaXplKCkpOyAKICAgICAgICByZXR1cm4gbGlzdDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyA8VCBleHRlbmRzIENvbXBhcmFibGU8VD4+IHZvaWQgcGFpck51dHNBbmRCb2x0cygKICAgICAgICAgICAgTGlzdDxQYWlyPE51dDxUPiwgQm9sdDxUPj4+IGxpc3QsCiAgICAgICAgICAgIExpc3Q8TnV0PFQ+PiBudXRzLCBMaXN0PEJvbHQ8VD4+IGJvbHRzLCBpbnQgbG8sIGludCBoaSkgewogICAgICAgIGlmIChoaSAtIGxvID09IDEpIHsKICAgICAgICAgICAgbGlzdC5hZGQobmV3IFBhaXI8PihudXRzLmdldChsbyksIGJvbHRzLmdldChsbykpKTsKICAgICAgICB9IGVsc2UgaWYgKGhpIC0gbG8gPiAxKSB7CiAgICAgICAgICAgIGludCBtaWQgPSBwYXJ0aXRpb24obnV0cywgYm9sdHMuZ2V0KGxvKSwgbG8sIGhpKTsKICAgICAgICAgICAgcGFydGl0aW9uKGJvbHRzLCBudXRzLmdldChtaWQpLCBsbywgaGkpOwogICAgICAgICAgICBsaXN0LmFkZChuZXcgUGFpcjw+KG51dHMuZ2V0KG1pZCksIGJvbHRzLmdldChtaWQpKSk7CgogICAgICAgICAgICBwYWlyTnV0c0FuZEJvbHRzKGxpc3QsIG51dHMsIGJvbHRzLCBsbywgbWlkKTsKICAgICAgICAgICAgcGFpck51dHNBbmRCb2x0cyhsaXN0LCBudXRzLCBib2x0cywgbWlkICsgMSwgaGkpOwogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyA8VCBleHRlbmRzIENvbXBhcmFibGU8VT4sIFU+IGludCBwYXJ0aXRpb24oCiAgICAgICAgICAgIExpc3Q8VD4gYXJyYXksIFUgcGl2b3QsIGludCBsbywgaW50IGhpKSB7CiAgICAgICAgZm9yIChpbnQgaSA9IGxvOyBpIDwgaGk7IGkrKykgewogICAgICAgICAgICBpZiAoYXJyYXkuZ2V0KGkpLmNvbXBhcmVUbyhwaXZvdCkgPT0gMCkgewogICAgICAgICAgICAgICAgc3dhcChhcnJheSwgbG8sIGkpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaW50IGlMZWZ0ID0gbG8sIGlSaWdodCA9IGhpOwogICAgICAgIGRvIHsKICAgICAgICAgICAgaUxlZnQrKzsKICAgICAgICAgICAgd2hpbGUgKGlMZWZ0IDwgaGkgLSAxCiAgICAgICAgICAgICAgICAgICAgJiYgYXJyYXkuZ2V0KGlMZWZ0KS5jb21wYXJlVG8ocGl2b3QpIDwgMCkgewogICAgICAgICAgICAgICAgaUxlZnQrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICBpUmlnaHQtLTsKICAgICAgICAgICAgd2hpbGUgKGlSaWdodCA+IGxvCiAgICAgICAgICAgICAgICAgICAgJiYgYXJyYXkuZ2V0KGlSaWdodCkuY29tcGFyZVRvKHBpdm90KSA+IDApIHsKICAgICAgICAgICAgICAgIGlSaWdodC0tOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChpTGVmdCA8IGlSaWdodCkgewogICAgICAgICAgICAgICAgc3dhcChhcnJheSwgaUxlZnQsIGlSaWdodCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgd2hpbGUgKGlMZWZ0IDwgaVJpZ2h0KTsKCiAgICAgICAgc3dhcChhcnJheSwgbG8sIGlSaWdodCk7CiAgICAgICAgcmV0dXJuIGlSaWdodDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyA8VD4gdm9pZCBzaHVmZmxlKExpc3Q8VD4gYXJyYXksIFJhbmRvbSByYW5kb20pIHsKICAgICAgICBmaW5hbCBpbnQgbiA9IGFycmF5LnNpemUoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IG4gLSAxOyBpKyspIHsKICAgICAgICAgICAgc3dhcChhcnJheSwgaSwgaSArIHJhbmRvbS5uZXh0SW50KG4gLSBpIC0gMSkgKyAxKTsKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgPFQ+IHZvaWQgc3dhcChMaXN0PFQ+IGFycmF5LCBpbnQgaSwgaW50IGopIHsKICAgICAgICBhc3NlcnQgaSA+PSAwICYmIGogPj0gMAogICAgICAgICAgICAmJiBpIDwgYXJyYXkuc2l6ZSgpICYmIGogPCBhcnJheS5zaXplKCk7CgogICAgICAgIFQgdGVtcCA9IGFycmF5LmdldChpKTsKICAgICAgICBhcnJheS5zZXQoaSwgYXJyYXkuZ2V0KGopKTsKICAgICAgICBhcnJheS5zZXQoaiwgdGVtcCk7CiAgICB9CgogICAgc3RhdGljIGNsYXNzIE51dDxUIGV4dGVuZHMgQ29tcGFyYWJsZTxUPj4KICAgICAgICAgICAgaW1wbGVtZW50cyBDb21wYXJhYmxlPEJvbHQ8VD4+IHsKICAgICAgICBwcml2YXRlIFQgdmFsdWU7IAoKICAgICAgICBwdWJsaWMgTnV0KFQgdmFsdWUpIHsKICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgICAgIH0KCiAgICAgICAgQE92ZXJyaWRlCiAgICAgICAgcHVibGljIGludCBjb21wYXJlVG8oQm9sdDxUPiBib2x0KSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlLmNvbXBhcmVUbyhib2x0LnZhbHVlKTsKICAgICAgICB9CgogICAgICAgIEBPdmVycmlkZQogICAgICAgIHB1YmxpYyBTdHJpbmcgdG9TdHJpbmcoKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpOwogICAgICAgIH0KICAgIH0KCiAgICBzdGF0aWMgY2xhc3MgQm9sdDxUIGV4dGVuZHMgQ29tcGFyYWJsZTxUPj4gCiAgICAgICAgICAgIGltcGxlbWVudHMgQ29tcGFyYWJsZTxOdXQ8VD4+IHsKICAgICAgICBUIHZhbHVlOwoKICAgICAgICBwdWJsaWMgQm9sdChUIHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgICAgICB9CgogICAgICAgIEBPdmVycmlkZQogICAgICAgIHB1YmxpYyBpbnQgY29tcGFyZVRvKE51dDxUPiBudXQpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUuY29tcGFyZVRvKG51dC52YWx1ZSk7CiAgICAgICAgfQoKICAgICAgICBAT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgU3RyaW5nIHRvU3RyaW5nKCkgewogICAgICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKTsKICAgICAgICB9CiAgICB9CgogICAgc3RhdGljIGNsYXNzIFBhaXI8VCwgVT4gewogICAgICAgIHByaXZhdGUgVCBmaXJzdDsKICAgICAgICBwcml2YXRlIFUgc2Vjb25kOwoKICAgICAgICBwdWJsaWMgUGFpcihUIGZpcnN0LCBVIHNlY29uZCkgewogICAgICAgICAgICB0aGlzLmZpcnN0ID0gZmlyc3Q7CiAgICAgICAgICAgIHRoaXMuc2Vjb25kID0gc2Vjb25kOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFQgZ2V0Rmlyc3QoKSB7CiAgICAgICAgICAgIHJldHVybiBmaXJzdDsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBVIGdldFNlY29uZCgpIHsKICAgICAgICAgICAgcmV0dXJuIHNlY29uZDsKICAgICAgICB9CgogICAgICAgIEBPdmVycmlkZQogICAgICAgIHB1YmxpYyBTdHJpbmcgdG9TdHJpbmcoKSB7CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcuZm9ybWF0KCIoJXMsICVzKSIsIGZpcnN0LCBzZWNvbmQpOwogICAgICAgIH0KICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewogICAgICAgIExpc3Q8TnV0PEludGVnZXI+PiBudXRzID0gbmV3IEFycmF5TGlzdDw+KCk7CiAgICAgICAgTGlzdDxCb2x0PEludGVnZXI+PiBib2x0cyA9IG5ldyBBcnJheUxpc3Q8PigpOwoKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IDEwOyBpKyspIHsKICAgICAgICAgICAgbnV0cy5hZGQobmV3IE51dDw+KGkpKTsKICAgICAgICAgICAgYm9sdHMuYWRkKG5ldyBCb2x0PD4oOSAtIGkpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChQYWlyPE51dDxJbnRlZ2VyPiwgQm9sdDxJbnRlZ2VyPj4gcGFpcgogICAgICAgICAgICAgICAgOiBwYWlyTnV0c0FuZEJvbHRzKG51dHMsIGJvbHRzKSkgewogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4ocGFpcik7CiAgICAgICAgfQogICAgfQp9