Pontue um jogo de Boggle

21

fundo

No Boggle , uma rodada é pontuada somando os pontos para cada palavra única que um jogador encontrou (ou seja, qualquer palavra que mais de um jogador tenha encontrado vale 0 ponto). Os pontos são calculados com base no número de letras em cada palavra, da seguinte maneira:

3 letras: 1 ponto

4 letras: 1 ponto

5 letras: 2 pontos

6 letras: 3 pontos

7 letras: 5 pontos

8 ou mais letras: 11 pontos

Desafio

Nesse desafio, escreva um programa ou função que inclua uma lista de listas de strings representando as palavras de cada jogador e produza uma lista das pontuações dos jogadores. Você pode assumir que haverá pelo menos 2 jogadores e todas as palavras terão 3 ou mais letras e serão todas em minúsculas (ou todas em maiúsculas, se preferir). Você também pode assumir que cada jogador usará cada palavra apenas uma vez; isto é, nenhuma lista de jogadores conterá duplicatas. Isso é código de golfe, então a resposta mais curta em bytes vence.

Regras

A entrada pode ser obtida em qualquer formato razoável. Os exemplos incluem uma lista de listas de strings, uma lista de strings separados por vírgula, uma string separada por vírgula em cada linha de entrada, etc. A saída pode estar na forma de uma lista de números inteiros (ou o equivalente no seu idioma) ou você pode imprimir os valores para stdout usando um separador de sua escolha (como uma nova linha).

Casos de teste

Entrada => Saída

[["cat","dog","bird","elephant"],
 ["bird","dog","coyote"],
 ["dog","mouse"]]                 => [12,3,2]

[["abc","def","ghi"],
 ["ghi","def","abc"]]             => [0,0]

[["programming","puzzles"],
 ["code","golf"],
 []]                              => [16,2,0]
Cowabunghole
fonte

Respostas:

6

Casca , 21 20 19 bytes

-2 bytes graças ao Zgarb

Ideia retirada de A055228

ṠṀöṁ(⌈√Π-3▼8L)fε`#Σ

Experimente online!

Explicação (da versão mais antiga)

            ṠṀ-oṠ-uΣ   Remove duplicated words
                   Σ   Concatenate
                  u    Remove duplicates
               oṠ-     Remove those unique elements from the list (give list of elements that appear more than once)
            ṠṀ-        Remove those words from each list in the input
m                      For each list
 ṁ(                    Map then sum
          L)           Length
        ▼8             Min(8,x)
      -3               Minus 3
     Π                 Factorial
    √                  Square root
   ⌈                   Ceiling
H.PWiz
fonte
20 bytes
Zgarb 19/09/17
Bom, não vou reorganizar, para economizar na explicação.
H.PWiz
19 bytes usando em fvez de-
Zgarb 20/09
Obrigado, eu não consegui fazer esse método funcionar sozinho.
H.PWiz
Gah! Pensei que eu tinha conseguido amarrá-lo, não tinha notado que você tinha 19 anos agora.
Shaggy
3

R , 142 126 121 117 bytes

function(L)sapply(lapply(L,setdiff,(l=unlist(L))[duplicated(l)]),function(x)sum(c(1,1,2,3,5,11)[pmin(6,nchar(x)-2)]))

Experimente online!

Toma Lcomo uma lista de vetores de strings; retorna os valores.

Primeiro, são unlistas palavras, encontra as duplicatas e as remove das listas de palavras dos jogadores. Em seguida, ele pega essas listas de palavras exclusivas e calcula as pontuações de cada uma delas, pminpara garantir que palavras com mais de 8 sejam pontuadas como 11.

Giuseppe
fonte
Você pode encurtar a 108 bytes, se você só tirar as duplicatas na função interna sapply:function(L)sapply(L,function(x)sum(c(1,1,2,3,5,11)[pmin(6,nchar(x[!x%in%(l=unlist(L))[duplicated(l)]])-2)]))
plannapus
3

JavaScript (ES6), 92 bytes

a=>a.map(b=>b.reduce((s,v)=>s+(a.filter(b=>b.includes(v))[1]?0:+"11235"[v.length-3]||11),0))

Um pouco semelhante à resposta de Rick Hitchcock, mas criada principalmente de forma independente; Eu usei um método diferente de summing ( reduce) e um método diferente para verificar termos repetidos ( filter+ includes). Crédito a ele pela idéia de verificar o item em [1]vez de verificar .length>1, no entanto.

Casos de teste

Justin Mariner
fonte
Você poderá salvar um byte usando s+=e removendo os parênteses ao redor dos ternários. E 3 mais, usando mapem vez de reduce: tio.run/##NY/...
Shaggy
Bem feito. Seu uso reducee includessua resposta são bem diferentes das minhas.
21717 Rick
3

JavaScript (ES6), 106 93 bytes

[Salvou 13 (!) Bytes, graças a Arnauld, Shaggy e JollyJoker.]

a=>a.map(b=>b.map(c=>x+=(a+'').split`,`.filter(d=>d==c)[1]?0:+'11235'[c.length-3]||11,x=0)|x)

Casos de teste:

Rick Hitchcock
fonte
2
Eu acho que você pode substituir c[7]?11:c[6]?5:c[5]?3:c[4]?2:1por '00011234'[c.length]||11.
Arnauld
Isso dá, em [15,2,0]vez do [16,2,0]último caso de teste, mas provavelmente isso é facilmente corrigido. Trabalhará um pouco mais depois do jantar, a menos que você poste uma resposta genial (como costuma fazer). Obrigado! :)
Rick Hitchcock
1
Ah sim, desculpe, deveria ser '00011235'.
Arnauld
1
Eu acho que você pode salvar mais alguns bytes em cima da sugestão de @ Arnauld assim .
Shaggy
1
Existem pelo menos 3 letras '11235'[c.length-3]||11, certo?
JollyJoker
2

Pitão , 26 bytes

Usa a fórmula de H.PWiz .

m+Fm.E@.!a3hS,8lk2fq1/sQTd

Verifique todos os casos de teste.

A versão inicial, 33 bytes :

m+Fm*h+++*6>lk7y>lk6>lk5glk3q1/sQ

Verifique todos os casos de teste.

Explicação

m + Fm * h +++ * 6> lk7y> lk6> lk5> glk3q1 / sQ Programa completo.

m Mapa sobre a entrada.
   m Mapa sobre cada sub-lista.
                        > lk3 O comprimento é superior a 2? 1 se verdadeiro e 0 se falso.
      +> lk5 Plus "tem um comprimento superior a 5?".
       + y> lk6 Plus "tem comprimento superior a 6?", dobrou.
        + * 6> lk7 Plus "tem comprimento superior a 7?", Vezes 6.
     h Incremento.
                            q1 / sQ Conte as ocorrências do elemento na planificação
                                     entrada e verifique se é igual a 1. 0 se Falso, 1 se Verdadeiro.
    * Multiplicação.
 + F Soma cada sub-lista.
Mr. Xcoder
fonte
2

Japt , 29 25 24 23 21 20 bytes

Ëx@èøX ¥1©3nXÊm8)ʬc

Tente


Explicação

Entrada implícita da matriz U.

Ëx@

Mapeie a matriz ( Ë) e reduza cada sub-matriz adicionando ( x) depois de passar seus elementos pela função a seguir, onde Xestá a palavra atual.

èøX

Count ( è) os elementos Uque contêm ( ø) X.

¥1

Verifique se é igual a 1.

©

AND lógico ( &&).

3nXÊm8)

Subtraia ( n) 3 do mínimo de ( m) 8 e do comprimento ( Ê) de X.

ʬc

Fatorial, raiz quadrada e arredondada, respectivamente.

Shaggy
fonte
2

Python 2 , 106 105 88 84 bytes

-1 byte graças a Jonathan Frech
-1 (17) bytes graças a reffu

lambda x:[sum(sum([1,0,1,1,2,6][:len(s)-2])*(`x`.count(`s`)<2)for s in l)for l in x]

Experimente online!

Cajado
fonte
105 bytes.
Jonathan Frech
104 bytes
reffu
@reffu obrigado, eu fiz algumas modificações no golfe ainda mais: 3
Rod
@ Rod Nice, eu esqueci o segundo parâmetro do truque de soma.
reffu
1

Geléia , 26 bytes

ðċ@Ị¥ÐfL€«8ị“¡[żÇ’ḃ11¤Sµ€Ẏ

Experimente online!

Erik, o Outgolfer
fonte
1

Java 8, 202 200 198 bytes

a->{int q=a.length,r[]=new int[q],i=0,j,f;for(;i<q;i++)for(String s:a[i]){for(f=j=0;j<q;)f|=a[j].contains(s)&!a[i].equals(a[j++])?1:0;if(f<1)r[i]+=(j=s.length())<5?1:j<6?2:j<7?3:j<8?5:11;}return r;}

OU (também 198 bytes )

a->{int q=a.length,r[]=new int[q],i=0,j,f=1,e=0;for(;i<q;r[i++]+=f<1?e<5?1:e<6?2:e<7?3:e<8?5:11:0)for(String s:a[i])for(f=j=0;j<q;e=s.length())f|=a[j].contains(s)&!a[i].equals(a[j++])?1:0;return r;}

Definitivamente, você pode jogar golfe .. Infelizmente, o Java não possui build-ins ou métodos curtos para remover todos os itens de todas as listas que estão presentes em múltiplos.

Explicação:

Experimente aqui.

a->{                       // Method with ArrayList<String>[] parameter & int[] return-type
  int q=a.length,          //  Length of the input-array
      r[]=new int[q],      //  Result integer-array the size of the input-array
      i=0,j,               //  Index integers
      f;                   //  Flag integer (used as boolean)
  for(;i<q;i++)            //  Loop (1) over the input array
    for(String s:a[i]){    //   Inner loop (2) over the Strings of the current List
      for(j=f=0;           //    Reset the flag `f` and index `j` both to 0
                j<q;)      //    Inner loop (3) over the input list again
        f|=a[j].contains(s)//     If the current list (3) contains the current String (2)
           &!a[i].equals(a[j++])?
                           //     and the current list (3) is not the current list (1)
            1              //      Bitwise-OR the flag with 1 (0->1; 1->1)
           :               //     Else:
            0;             //      Bitwise-OR the flag with 0 (0->0; 1->1)
                           //    End of inner loop (3) (implicit / single-line body)
      if(f<1)              //    If the flag is still 0 (so the current String is unique)
        r[i]+=             //     Increase the current item in the result integer-array by:
              (j=s.length())<5?
                           //      If the length is below 5:
               1           //       By 1
              :j<6?        //      Else-if the length is below 6:
               2           //       By 2
              :j<7?        //      Else-if the length is below 7:
               3           //       By 3
              :j<8?        //      Else-if the length is below 8:
               5           //       By 5
              :            //      Else (above 7):
               11;         //       By 11
    }                      //   End of inner loop (2)
                           //  End of loop (1) (implicit / single-line body)
  return r;                //  Return the resulting integer-array
}                          // End of method
Kevin Cruijssen
fonte
Adoro ternários, e a única coisa que odeio no ScaLa é que eles removeram essa sintaxe ternária.
V. Courtois
@ V.Courtois Hmm, por curiosidade, como está a sintaxe ternária em Scala agora?
Kevin Cruijssen 26/09
uh: if (bool1) exp1 else exp2
V. Courtois
1

R, 117 bytes

Uma abordagem completamente diferente da outra resposta R :

function(L)sapply(L,function(x)sum(c(0:3,5,11)[cut(nchar(x[x%in%names(which(table(unlist(L))<2))]),c(0,2,4:7,Inf))]))

Casos de teste:

> f=function(L)sapply(L,function(x)sum(c(0:3,5,11)[cut(nchar(x[x%in%names(which(table(unlist(L))<2))]),c(0,2,4:7,Inf))]))
> L=list(c("cat","dog","bird","elephant"),c("bird","dog","coyote"),c("dog","mouse"))
> f(L)
[1] 12  3  2
> L=list(c("abc","def","ghi"),c("ghi","def","abc"))
> f(L)
[1] 0 0
> L=list(c("programming","puzzles"),c("code","golf"),c())
> f(L)
[1] 16  2  0

Pega os nomes que ocorrem apenas uma vez na lista, converte seu comprimento em um fator com base nos pontos de corte especificados e converte isso em pontuações que são somadas.

plannapus
fonte
114 bytes combinando nossas duas abordagens na etapa de desduplicação.
Giuseppe
0

Perl 5 , 104 + 2 (-na) = 106 bytes

push@a,[@F];map$k{$_}++,@F}{map{$s=0;map$s+=(($l=y///c)<8?$l<7?$l<5?1:$l-3:5:11)*($k{$_}<2),@$_;say$s}@a

Experimente online!

Xcali
fonte
0

Clojure, 102 bytes

#(for[p %](apply +(for[w p](if(next(filter #{w}(flatten %)))0(get{3 1 4 1 5 2 6 3 7 5}(count w)11)))))

nextretorna nilse houver apenas uma palavra w:)

NikoNyrh
fonte
0

PHP , 226 bytes

function x($a){foreach($a as$p){$q=call_user_func_array('array_diff',$a);array_push($a,array_shift($a));$x=0;array_map(function($b)use(&$x){$b=strlen($b);$x+=($b<5?1:($b==5?2:($b==6?3:($b==7?5:11))));},$q);$o[]=$x;}return $o;}

Eu acho que isso ainda pode ser um pouco reduzido.

Ungolfed:

function x($a) {
    foreach ($a as $p) {
        $q = call_user_func_array('array_diff', $a);
        array_push($a, array_shift($a));
        $x = 0;
        array_map(function($b) use (&$x){
            $b = strlen($b);
            $x += ($b < 5 ? 1 : ($b == 5 ? 2 : ($b == 6 ? 3 : ($b == 7 ? 5 : 11))));
        }, $q);
        $o[] = $x;
    }
    return $o;
}

Experimente online!

Samsquanch
fonte
0

Scala , 242 bytes

A função recebe, como parâmetro a, Seq[Set[String]]ae retorna an Array[Int]. Eu uso uma matriz para que seja mutável (perda de 4 caracteres).

var s=Seq("")
a.foreach(x=>x.foreach(y=>s:+=y))
var u:Array[Int]=Array()
var i= -1
a.foreach(t=>{i+=1
u:+=0
t.map(x=>{val l=x.length
if(s.count(_==x)<2){if(l>7)u(i)+=11
if(l==7)u(i)+=5
if(l==6)u(i)+=3
if(l==5)u(i)+=2
if(l>2&l<5)u(i)+=1}})})
u

Experimente online!

Pode ser otimizado, já que eu nem trabalhei no

if(l>7)u(i)+=11
if(l==7)u(i)+=5
if(l==6)u(i)+=3
if(l==5)u(i)+=2
if(l>2&l<5)u(i)+=1

parte. Obrigado por este desafio!

V. Courtois
fonte
0

Swift 4 , 164 bytes *

{$0.map{Set($0).subtracting(Dictionary(grouping:$0.flatMap{$0},by:{$0}).flatMap{$1.count != 1 ?$0:nil}).map{[0,1,1,2,3,5,11][min(max($0.count-2,0),6)]}.reduce(0,+)}}

A expressão acima é tecnicamente correta, pura Swift. No entanto, a expressão é tão complexa que, devido a uma explosão exponencial no sistema de inferência de tipo, não pode ser processada antes que o compilador desista após um tempo limite arbitrário (como 15s ou algo assim).

Para tornar essa expressão compilável com o compilador atual, ela pode ser dividida assim:

{
let n = Dictionary(grouping:$0.flatMap{$0},by:{$0}).flatMap{$1.count != 1 ?$0:nil}
return $0.map{Set($0).subtracting(n).map{[0,1,1,2,3,5,11][min(max($0.count-2,0),6)]}.reduce(0,+)}
}

Casos de teste:

let f: (_ input: [[String]]) -> [Int] = {
    let n = Dictionary(grouping:$0.flatMap{$0},by:{$0}).flatMap{$1.count != 1 ?$0:nil}
    return $0.map{Set($0).subtracting(n).map{[0,1,1,2,3,5,11][min(max($0.count-2,0),6)]}.reduce(0,+)}
}

let testcases: [(input: [[String]], expected: [Int])] = [
    (input: [
            ["cat","dog","bird","elephant"],
            ["bird","dog","coyote"],
            ["dog","mouse"]
        ],
        expected: [12,3,2]
    ),
    (input: [
            ["abc","def","ghi"],
            ["ghi","def","abc"]
        ],
        expected: [0,0]
    ),
    (input: [
            ["programming","puzzles"],
            ["code","golf"],
            []
        ],
        expected: [16,2,0]
    ),
]

for (caseNumber, testcase) in testcases.enumerated() {
    let actual = f(testcase.input)
    assert(actual == testcase.expected,
        "Testcase #\(caseNumber) \(testcase.input) failed. Got \(actual), but expected \(testcase.expected)!")
    print("Testcase #\(caseNumber) passed!")
}

Quebrado:

let verboseF: (_ input: [[String]]) -> [Int] = { playerHands in
    let allWords = playerHands.flatMap{$0}
    // demo data for first test case:
    // allWords: ["cat", "dog", "bird", "elephant", "bird", "dog", "coyote" "dog", "mouse"]

    let allWordsGroupedByThemselves = Dictionary(grouping: allWords, by: {$0})
    /* allWordsGroupedByThemselves:
    [
        "cat": ["cat"],
        "dog": ["dog", "dog", "dog"],
        "bird": ["bird", "bird"],
        "elephant": ["elephant"],
        "coyote": ["coyote"], "mouse": ["mouse"]
    ]*/

    let allWordsUsedMoreThanOnce = allWordsGroupedByThemselves.flatMap{$1.count != 1 ?$0:nil}
    // allWordsUsedMoreThanOnce: ["dog", "bird"]

    return playerHands.map{ hand in
        // demo data for first hand of first test case:
        // hand: ["cat","dog","bird","elephant"]

        let uniqueWordsInHand = Set(hand)
        // uniqueWordsInHand: ["cat","dog","bird","elephant"]

        let uniqueWordsInHandNotUsedByOthers = uniqueWordsInHand.subtracting(allWordsUsedMoreThanOnce)
        // uniqueWordsInHandNotUsedByOthers: ["cat", "elephant"]

        let wordLengths = uniqueWordsInHandNotUsedByOthers.map{$0.count}
        // wordLengths: [3, 8]

        let scores = wordLengths.map{ wordLength in
            return [0,1,1,2,3,5,11][min(max(wordLength-2, 0), 6)] //A look up table that maps word length to word score
        }
        //scores: [1, 11]

        let playerScore = scores.reduce(0,+)
        // playerScore: 12

        return playerScore
    }
}
Alexander - Restabelecer Monica
fonte
0

ASP + Python , 137 bytes

u(P,W):-1{p(_,W)}1;p(P,W).s(P,S):-S=#sum{@v(W):u(P,W)};p(P,_).#script(python)
def v(w):return[1,1,2,3,5,11][min(len(w.string),8)-3]#end.

Espera dados formatados como:

p(1,("cat";"dog";"bird";"elephant")).
p(2,("bird";"dog";"coyote")).
p(3,("dog";"mouse")).

Precisa de clingo 5.2.1 com suporte a python.

Ungolfed:

unique(P,W):- 1 { player(_,W) } 1 ; player(P,W).
score(P,S):- S = #sum{@value(W): unique(P,W)} ; player(P,_).
#script (python)
def value(word):
    return [1,1,2,3,5,11][min(len(word.string),8)-3]
#end.

A função python é fortemente inspirada na resposta python .

aluriak
fonte