Anotar un juego de Boggle

21

Fondo

En Boggle , una ronda se puntúa sumando los puntos por cada palabra única que haya encontrado un jugador (es decir, cualquier palabra que haya encontrado más de un jugador vale 0 puntos). Los puntos se calculan en función del número de letras en cada palabra, de la siguiente manera:

3 letras: 1 punto

4 letras: 1 punto

5 letras: 2 puntos

6 letras: 3 puntos

7 letras: 5 puntos

8 o más letras: 11 puntos

Reto

En este desafío, escriba un programa o función que incluya una lista de listas de cadenas que representen las palabras de cada jugador y genere una lista de las puntuaciones de los jugadores. Puede suponer que habrá al menos 2 jugadores y todas las palabras serán de 3 o más letras y todas estarán en minúsculas (o todas en mayúsculas si lo prefiere). También puede suponer que cada jugador solo usará cada palabra una vez; es decir, ninguna lista de jugadores contendrá duplicados. Este es el código de golf, por lo que la respuesta más corta en bytes gana.

Reglas

La entrada puede tomarse en cualquier formato razonable. Los ejemplos incluyen una lista de listas de cadenas, una lista de cadenas separadas por comas, una cadena separada por comas en cada línea de entrada, etc. La salida puede tener la forma de una lista de enteros (o el equivalente de su idioma) o puede imprimir los valores para stdout utilizando un separador de su elección (como una nueva línea).

Casos de prueba

Entrada => Salida

[["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]
Agujero de vaca
fuente

Respuestas:

6

Casco , 21 20 19 bytes

-2 bytes gracias a Zgarb

Idea tomada de A055228

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

Pruébalo en línea!

Explicación (de la versión anterior)

            ṠṀ-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
fuente
20 bytes
Zgarb
Agradable, no voy a reorganizar, para ahorrar en la explicación.
H.PWiz
19 bytes usando en flugar de-
Zgarb
Gracias, no pude conseguir que ese método funcionara yo mismo.
H.PWiz
Gah! Pensé que había logrado atarte, no me había dado cuenta de que ahora tienes 19 años.
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)]))

Pruébalo en línea!

Toma Lcomo una lista de vectores de cadenas; Devuelve los valores.

Primero, son unlistlas palabras, encuentra los duplicados, luego los elimina de las listas de palabras de los jugadores. Luego toma estas listas de palabras únicas y calcula los puntajes de cada una, pminpara asegurarse de que las palabras de más de 8 se califiquen como 11.

Giuseppe
fuente
Puede acortarlo a 108 bytes si solo quita los duplicados en la función 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))

Algo similar a la respuesta de Rick Hitchcock pero creada principalmente de forma independiente; Utilicé un método diferente de suma ( reduce) y un método diferente para verificar términos repetidos ( filter+ includes). Sin embargo, le atribuimos la idea de verificar el artículo en [1]lugar de verificarlo .length>1.

Casos de prueba

Justin Mariner
fuente
Debería poder guardar un byte utilizando s+=y eliminando los paréntesis alrededor de los ternarios. Y 3 más usando en maplugar de reduce: tio.run/##NY/…
Shaggy
Bien hecho. Su uso de reducey includeshace que su respuesta sea bastante diferente a la mía.
Rick Hitchcock
3

JavaScript (ES6), 106 93 bytes

[Guardado 13 (!) Bytes, gracias a Arnauld, Shaggy y 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 prueba:

Rick Hitchcock
fuente
2
Creo que puedes reemplazarlo c[7]?11:c[6]?5:c[5]?3:c[4]?2:1con '00011234'[c.length]||11.
Arnauld
Eso da en [15,2,0]lugar del [16,2,0]último caso de prueba, pero eso probablemente se arregle fácilmente. Trabajará un poco más después de la cena, a menos que publique una respuesta genial (como suele hacer). ¡Gracias! :)
Rick Hitchcock
1
Ah sí, lo siento, eso debería ser '00011235'.
Arnauld
1
Creo que puede guardar otros pocos bytes además de la sugerencia de @ Arnauld de esta manera .
Shaggy
1
Hay al menos 3 letras, '11235'[c.length-3]||11¿verdad?
JollyJoker
2

Pyth , 26 bytes

Utiliza la fórmula de H.PWiz .

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

Verifique todos los casos de prueba.

La versión inicial, 33 bytes :

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

Verifique todos los casos de prueba.

Explicación

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

m Mapa sobre la entrada.
   m Mapa sobre cada sublista.
                        > lk3 ¿La longitud es mayor que 2? 1 si es verdadero y 0 si es falso.
      +> lk5 Plus "tiene una longitud superior a 5?".
       + y> lk6 Plus "tiene una longitud superior a 6?", duplicado.
        + * 6> lk7 Plus "es una longitud superior a 7?", Multiplicado por 6.
     h Incremento.
                            q1 / sQ Cuenta las apariciones del elemento en el plano
                                     entrada y compruebe si es igual a 1. 0 si es falso, 1 si es verdadero.
    * Multiplicación.
 + F Suma cada sublista.
Sr. Xcoder
fuente
2

Japt , 29 25 24 23 21 20 bytes

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

Intentalo


Explicación

Entrada implícita de la matriz U.

Ëx@

Asigne sobre el conjunto ( Ë) y reduzca cada subconjunto mediante la suma ( x) después de pasar sus elementos a través de la siguiente función, donde Xestá la palabra actual.

èøX

Cuenta ( è) los elementos Uque contienen ( ø) X.

¥1

Compruebe si eso es igual a 1.

©

Lógico Y ( &&).

3nXÊm8)

Reste ( n) 3 del mínimo de ( m) 8 y la longitud ( Ê) de X.

ʬc

Factorial, raíz cuadrada y redondeada, respectivamente.

Lanudo
fuente
2

Python 2 , 106 105 88 84 bytes

-1 byte gracias a Jonathan Frech
-1 (17) bytes gracias 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]

Pruébalo en línea!

Barra
fuente
105 bytes.
Jonathan Frech
104 bytes
reffujo
@reffu gracias, he hecho algunas modificaciones al golf aún más: 3
Rod
@ Rod Nice, olvidé el segundo parámetro del truco de la suma.
reffujo
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;}

O (también 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 se puede jugar golf. Desafortunadamente Java no tiene complementos ni métodos cortos para eliminar todos los elementos de todas las listas que están presentes en múltiples ...

Explicación:

Pruébalo aquí

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
fuente
Me encantan los ternarios, y lo único que odio de ScaLa es que eliminaron esta sintaxis ternaria.
V. Courtois
@ V.Courtois Hmm, por curiosidad, ¿cómo es la sintaxis ternaria en Scala ahora?
Kevin Cruijssen
uh: if (bool1) exp1 else exp2
V. Courtois
1

R, 117 bytes

Un enfoque completamente diferente de la otra respuesta 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 prueba:

> 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

Toma los nombres que aparecen solo una vez en la lista, convierte su longitud a un factor basado en los puntos de corte dados y los traduce en puntajes que luego se suman.

plannapus
fuente
114 bytes combinando nuestros dos enfoques en el paso de deduplicación.
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

Pruébalo en línea!

Xcali
fuente
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)))))

nextvuelve nilsi solo hay una palabra w:)

NikoNyrh
fuente
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;}

Creo que esto aún podría reducirse bastante.

Sin golf:

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;
}

Pruébalo en línea!

Samsquanch
fuente
0

Scala , 242 bytes

La función toma, como parámetro a, a Seq[Set[String]]y devuelve un Array[Int]. Utilizo una matriz para que sea mutable (pérdida 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

Pruébalo en línea!

Podría ser optimizable, ya que ni siquiera trabajé en el

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. ¡Gracias por este desafío!

V. Courtois
fuente
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,+)}}

La expresión anterior es técnicamente correcta, pura Swift. Sin embargo, la expresión es tan compleja que, debido a la explosión exponencial en el sistema de inferencia de tipos, no se puede procesar antes de que el compilador se rinda después de un tiempo de espera arbitrario (como 15 segundos o algo así).

Para hacer que esta expresión sea compatible con el compilador actual, puede desglosarse así:

{
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 prueba:

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!")
}

Desglosado:

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 - Restablece a Monica
fuente
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 datos formateados como:

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

Necesita clingo 5.2.1 con soporte para python.

Sin golf:

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.

La función de Python está muy inspirada en la respuesta de Python .

aluriak
fuente