読者です 読者をやめる 読者になる 読者になる

素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: すかいぷ:javascripter_  か javascripter あっと tsukkun.net skypeのほうがいいです

カード配り問題

10分でコーディング|プログラミングに自信があるやつこい!!を見て、僕だったらどう書くかなと考えた。
まず、10分で解くことを目標に急いで書いた物。最後のほう読むの忘れて引数名などをミスった。

function range(start, end) {
  var a = [];
  var i;
  for (i = start; i < end; i++) {
    a.push(i);
  }
  return a;
}

function distribute(number, cards) {
  return cards.length < number ?
    range(0, number).map(function () { return ""; }) :
    range(0, cards.length - cards.length % number).map(function (i) {
    return { card: cards.charAt(i), by: i % number };
  }).sort(function (a, b) {
    return a.by - b.by;
  }).reduce(function (cards, card) {
    return card.by >= cards.length ?
      [card.card].concat(cards) :
      [cards[0] + card.card].concat(cards.slice(1));
  }, [])
  .reverse();
}

8分くらいで途中まで書いて、残りの2分でテストしつつcards.length < numberの場合の条件分岐を追加…。
とりあえず10分で解けることは分かったので、

var eqv = function (a, b) {
  return a.length == b.length &&
    a.every(function (value, i) {
      return value == b[i];
    });
};

console.assert(eqv(distribute(3, "123123123"), ["111","222","333"]));
console.assert(eqv(distribute(4, "123123123"), ["12","23","31","12"]));
console.assert(eqv(distribute(6, "012345012345012345"), ["000", "111", "222", "333", "444", "555"]));
console.assert(eqv(distribute(4, "111122223333"), ["123", "123", "123", "123"]));
console.assert(eqv(distribute(1, "012345012345012345"), ["012345012345012345"]));
console.assert(eqv(distribute(6, "01234"), ["", "", "", "", "", ""]));
console.assert(eqv(distribute(2, ""), ["", ""]));

テストを追加。人間のようにカードを一枚ずつ分配するのではなく、一度にプレーヤーに配れば、もっと簡単にできるよなあ…、と思って書いたら

function distribute(number, cards) {
  return range(0, number).map(function (player) {
    return range(0, cards.length - cards.length % number)
      .filter(function (i) { return i % number == player; })
      .map(function (i) {
        return cards.charAt(i);
      })
      .join("");
  });
}

こんな感じになった。んー…。まあマシにはなったけど、10分で出来ないと意味ないなあ。(オチ無し)