将列表拆分为其他列表和其他问题

时间:2013-12-09 16:44:51

标签: ceylon

我还没有完全验证正确性和缺少一个错误,但请耐心等待一段时间。

此处的目标是将一副牌(定义为{Card *})交易/拆分为多个牌组(可选择将{Card *}作为构造函数参数)。我想以循环方式分割卡片,就像卡片实际上会被处理一样。这是我到目前为止的代码:

{Deck*} split(Integer ways) {
    assert(theCards.size % ways == 0);
    {Card*} empty = {};
    value decks = LinkedList { for (i in 0:ways) empty };
    for(i -> card in entries(theCards)) {
        value deckIndex = i % ways;
        assert (exists current = decks[deckIndex]);
        decks.set(deckIndex, {card, *current});
    }
    return { for(cards in decks) Deck(cards) };
}
  1. 这是将列表拆分成多个列表的正确/惯用方式吗?
  2. 如果我想反转所有卡片(即,附加到列表而不是前置,或者反转可迭代)我该怎么做?
  3. 如何在循环内懒洋洋地初始化decks变量的值?
  4. 我有什么方法可以避免需要empty变量吗?
  5. 我是否有机会在不需要可变数据结构的情况下编写本文?
  6. 谢谢,抱歉这个多问题(我已经在codereview.stackexchange.com上创建了这个,但我没有代表在那里创建ceylon标签)。

2 个答案:

答案 0 :(得分:4)

没有逆转,懒惰,没有可变数据结构:

alias Card => String;

{{Card*}*} deal({Card*} cards, Integer players)
        => {for (i in 0:players) cards.skipping(i).by(players)};

void run() {
    value suits = {"♦", "♣", "♥", "♠"};
    value ranks = {for (i in 2..10) i.string}.chain{"J", "Q", "K", "A"};
    value deck = {for (suit in suits) for (rank in ranks) rank + suit};
    print(deal(deck.taking(10), 2)); // { { 2♦, 4♦, 6♦, 8♦, 10♦ }, { 3♦, 5♦, 7♦, 9♦, J♦ } }
}

懒惰和不可变的风格是以每只手的所有牌重复为代价的。我更喜欢这个急切的解决方案:

{Card[]*} deal({Card*} cards, Integer players) {
    value hands = [for (i in 0:players) SequenceBuilder<Card>()];
    for (card->hand in zipEntries(cards, hands.cycled)) {
        hand.append(card);
    }
    return {for (hand in hands) hand.sequence};
}

这样,你只需要迭代一次。


请注意,Ceylon的枚举类型提供了一种很好的方式来表示类型安全和面向对象方式的套装和排名,类似于Java的枚举:

abstract class Suit(shared actual String string)
        of diamonds | clubs | hearts | spades {}

object diamonds extends Suit("♦") {}
object clubs extends Suit("♣") {}
object hearts extends Suit("♥") {}
object spades extends Suit("♠") {}

答案 1 :(得分:1)

如下:

alias Deck => {Card*};

{Deck*} split(Deck cards, Integer ways) {
    assert(ways.divides(cards.size));
    return { for i in (0:ways) { for (j->card in entries(cards)) if (j%ways==i) card } };
}

如果Deck实际上是一个类,从您的描述中不是很清楚,那么:

class Deck(shared {Card*} cards) { ... }

{Deck*} split(Deck deck, Integer ways) {
    assert(ways.divides(deck.cards.size));
    return { for i in (0:ways) Deck { for (j->card in entries(deck.cards)) if (j%ways==i) card } };
}

注意:我没有测试过这个。

相关问题