public static Collection<Coin> exchange( Coin orig) {
        // 1円は両替不可
        if ( orig.equals( oneYenCoin())) {
            return Arrays.asList( orig);
        }
        final Coin upperBounds = orig;
        // origよりも安いけれど、金額の高い順にコインを1種類ずつ保持
        ImmutableSortedSet<Coin> coinSet = ImmutableSortedSet.copyOf( //
            descComparator(), //
            Collections2.filter( getOneOfEach(), new Predicate<Coin>() {
                @Override
                public boolean apply( Coin o) {
                    if ( o == null) {
                        return false;
                    }
                    return o.compareTo( upperBounds) < 0;
                }
            }));
        Collection<Coin> result = Lists.newArrayList();

        Yen remaining = orig.getAmount();
        for ( Coin coin : coinSet) {
            while ( remaining.compareTo( coin.getAmount()) >= 0) {
                remaining = remaining.subtract( coin.getAmount());

                if ( remaining.compareTo( Yen.zero()) < 0) {
                    throw new AssertionError();
                }

                result.add( coin);

                if ( remaining.compareTo( Yen.zero()) == 0) {
                    return result;
                }
            }
        }
        throw new AssertionError();
    }