Encuentra el rango de una palabra


23

Definición

El rango de una palabra se define como la posición de la palabra cuando todas las permutaciones (o arreglos) posibles de sus letras se ordenan alfabéticamente, como en un diccionario, sin importar si las palabras son significativas o no.

Consideremos estas dos palabras: "azul" y "visto". Para comenzar, escribiríamos todos los arreglos posibles de las letras de estas palabras en orden alfabético:

"blue": "belu","beul","bleu","blue","buel","bule","eblu","ebul","elub","elbu","eubl",
        "eulb","lbeu","lbue","lebu","leub","lube","lueb","ubel","uble","uebl","uelb",
        "ulbe","uleb"
"seen": "eens","eesn","enes","ense","esen","esne","nees","nese","nsee","seen",
        "sene","snee"

Ahora miremos desde la izquierda y encontremos la posición de las palabras que necesitamos. Vemos que la palabra "azul" está en la cuarta posición y "visto" está en la décima posición. Entonces, el rango de la palabra "azul" es 4, y el de "visto" es 10. Esta es la forma general de calcular el rango de una palabra. Asegúrese de comenzar a contar solo desde 1.

Tarea

Su tarea es escribir un código para tomar cualquier palabra como entrada y mostrar su rango. El rango debe ser la salida. Tenga cuidado con las palabras que contienen letras repetidas.

Ejemplos

"prime" -> 94

"super" -> 93

"bless" -> 4

"speech" -> 354

"earth" -> 28

"a" -> 1

"abcd" -> 1

"baa" -> 3    

Puede suponer que la entrada está completamente en minúsculas y la entrada solo contendrá caracteres alfabéticos . Además, si se ingresa un espacio en blanco o una cadena no válida, puede devolver cualquier cosa.

Tanteo

Este es el , por lo que gana el código más corto.



14
"Asegúrese de comenzar a contar solo desde 1". - Es totalmente de usted tener este requisito, pero tenga en cuenta que es bastante común permitir la indexación basada en 0 o 1 para tales desafíos.
Jonathan Allan

1
Sí, ikr, pero si comienzas desde 0, en realidad no estás mostrando el rango original, por eso decidí agregar este requisito.
Manish Kundu

Enlace útil . Obtendrá AC si su programa se ejecuta a tiempo O(n log n)o menos. (lo siento, no Python) Mi envío (C ++) toma 2.53s para resolver la prueba 14.
user202729

¿Puedo hacer una tupla o una lista con esa palabra, por ejemplo, ['h', 'e', 'l', 'l', 'o']en lugar de 'hello'?
0WJYxW9FMN

Respuestas:





4

Pyth , 6 bytes

hxS{.p

Banco de pruebas.

Explicación

hxS {.p || Programa completo

    .p || Todas las permutaciones de la entrada.
   {|| Deduplicar
  S || Ordenar.
 x || Índice de la entrada en esta lista.
h || Incremento.

3

Jalea , 5 bytes

Œ!ṢQi

Pruébalo en línea! o ver el conjunto de pruebas

Cómo funciona

Œ!ṢQi - Main link. Argument: s (string)      e.g. 'baa'
Œ!    - All permutations                          ['baa', 'baa', 'aba', 'aab', 'aba', 'aab']
  Ṣ   - Sort                                      ['aab', 'aab', 'aba', 'aba', 'baa', 'baa']
   Q  - Deduplicate                               ['aab', 'aba', 'baa']
    i - 1-based index of s                        3

Falla en palabras que contienen letras repetidas.
Manish Kundu

@ManishKundu y Xcoder, arreglado
caird coinheringaahing

Lamentablemente Œ¿no funciona.
user202729

Funciona ṢŒ¿?
Esolanging Fruit

@EsolangingFruit No, eso solo da como resultado1
caird coinheringaahing




2

Japt , 8 10 bytes

0 indexado. ¡Poxy, indexación 1 innecesaria, aumentando mi recuento de bytes en un 25%!

á â n bU Ä

Pruébalo


Explicación

á obtiene todas las permutaciones de la entrada, â Elimina los duplicados, nlos ordena y bobtiene el índice de la primera aparición de la entrada, U.


Tenga en cuenta el requisito (inusual) "Asegúrese de comenzar a contar desde 1 solamente". He comentado bajo el OP que sería normal permitir también basado en 0.
Jonathan Allan

1
Ah, maldita sea; stoopid 1-indexing. Se actualizará en breve, pero aumentará mi recuento de bytes en un 25%.
Shaggy

2

J , 28 23 bytes

-5 bytes gracias a FrownyFrog

1+/:~@~.@(A.~i.@!@#)i.]

¿Cómo funciona?

                      ] - the argument
         (A.~      )    - permutations in the 
             i.@!@#     - range 0 to factorial of the arg. length
  /:~@~.@               - remove duplicates and sort
                    i.  - index of arg. in the sorted list
1+                      - add 1 (for 1-based indexing)

Pruébalo en línea!


1
23:1+/:~@~.@(A.~i.@!@#)i.]
FrownyFrog

@FrownyFrog - Buen uso de i. para encontrar el índice! ¡Gracias!
Galen Ivanov

El enlace TIO sigue siendo la versión anterior :)
Conor O'Brien

@Conor O'Brien - arreglado
Galen Ivanov

Como de costumbre no estoy feliz hasta que consiga una solución de K que es más corto que el J uno. Dicho esto, ¿puedes usar el mismo truco aquí? ¿Generar permutaciones de la cadena de entrada ordenada (por lo tanto, elimina la necesidad de ordenar la lista permutada)?
Callejero

2

Tcl, 196 bytes

proc p {a p} {if {$a eq {}} {lappend ::p $p} {while {[incr n]<=[llength $a]} {p [lreplace $a $n-1 $n-1] $p[lindex $a $n-1]}}}
p [split $argv ""] ""
puts [expr [lsearch [lsort -unique $p] $argv]+1]

Tcl no tiene un método incorporado para calcular la próxima permutación lexicográfica, por lo que debemos hacerlo nosotros mismos. Pero espera ... es más corto hacerlo con una función recursiva simple que calcula todas las permutaciones posibles en cualquier orden.

Sin golf:

# Compute all possible permutations of the argument list
# Puts the result in ::all_permutations
proc generate_all_permutations {xs {prefixes ""}} {
  if {$xs eq {}} {
    lappend ::all_permutations $prefixes
  } else {
    while {[incr n] <= [llength $xs]} {
      generate_all_permutations [lreplace $xs $n-1 $n-1] $prefixes[lindex $xs $n-1]
    } 
  }
}

# Get our input as command-line argument, turn it into a list of letters
generate_all_permutations [split $argv ""]

# Sort, remove duplicates, find the original argument, and print its 1-based index
puts [expr [lsearch [lsort -unique $all_permutations] $argv]+1]


Más afeitado tio.run/…
sergiol

Gracias. Cuando vuelva a tener acceso a una computadora real, actualizaré.
Dúthomhas

2

K (oK) , 23 18 bytes

Solución:

1+*&x~/:?x@prm@<x:

Pruébalo en línea!

Ejemplos:

1+*&x~/:?x@prm@<x:"seen"
10
1+*&x~/:?x@prm@<x:"blue"
4

Explicación:

Genere permutaciones de los índices de la cadena de entrada ordenada, úselas para indexar nuevamente en la cadena de entrada, tome las distinciones, vea dónde coincide la cadena original y agregue una.

1+*&x~/:?x@prm@<x: / the solution
                x: / save input string as x
               <   / return indices when sorting x ascending
           prm@    / apply (@) function prm
         x@        / index into x with these permutations
        ?          / distinct (remove duplicates)
    x~/:           / apply match (~) between x and each-right (/:)
   &               / return indexes where true (ie the match)
  *                / take the first one
1+                 / add 1 due to 1-indexing requirement

2

Java 8, 211 bytes

import java.util.*;TreeSet q=new TreeSet();s->{p("",s);return-~q.headSet(s).size();}void p(String p,String s){int l=s.length(),i=0;if(l<1)q.add(p);for(;i<l;p(p+s.charAt(i),s.substring(0,i)+s.substring(++i,l)));}

Explicación:

Pruébalo en línea.

import java.util.*;        // Required import for TreeSet

TreeSet q=new TreeSet();   // Sorted Set on class-level

s->{                       // Method with String parameter and integer return-type
  p("",s);                 //  Save all unique permutations of the String in the sorted set
  return-~q.headSet(s).size();}
                           //  Return the 0-indexed index of the input in the set + 1

void p(String p,String s){ // Separated method with 2 String parameters and no return-type
  int l=s.length(),        //  The length of the String `s`
      i=0;                 //  Index integer, starting at 0
  if(l<1)                  //  If String `s` is empty
    q.add(p);              //   Add `p` to the set
  for(;i<l;                //  Loop from 0 to `l` (exclusive)
    p(                     //   Do a recursive call with:
      p+s.charAt(i),       //    `p` + the character at the current index of `s` as new `p`
      s.substring(0,i)+s.substring(++i,l)));}
                           //    And `s` minus this character as new `s`

2

Python 3 , 183 182 bytes

La primera respuesta que se ejecuta en tiempo polinomial!

a=[*map(ord,input())]
f=lambda x:x and x*f(x-1)or 1
c=[0]*98
for C in a:c[C]+=1
l=len(a)
F=f(l)
for i in c:F//=f(i)
r=1
for x in a:F//=l;l-=1;r+=sum(c[:x])*F;F*=c[x];c[x]-=1
print(r)

Pruébalo en línea!

Requiere que la entrada sea todo en mayúsculas, porque ... guarda un byte.

Programa completo, toma entrada stdiny salida a stdout.


Nombres de variables: (tipo de código no protegido)

a : permu
f : factorial
c : count_num
C : char
l : n_num_left
F : factor
r : result

Desafortunadamente, from math import factorial as ftoma exactamente 1 byte más.


(Nota no relacionada: revisé el Combinatorica`paquete de Mathematica, nada útil, incluido RankPermutation)


Ese código es realmente bueno.
Manish Kundu

1

Casco , 6 bytes

S€(OuP

Pruébalo en línea! Siento que debería haber una manera de caer (.

Explicación:

 €     -- return index of the input 
S (    -- in the list generated by applying the following functions to the input:
     P -- permutations
    u  -- remove duplicates
   O   -- sort

1

Limpio , 113 111 bytes

import StdEnv,StdLib
?s=elemIndex s[[]:removeDup(foldr(\a b=sort[insertAt i a x\\x<-b,i<-[0..length x]])[[]]s)]

Pruébalo en línea!

+3 bytes para manejar la indexación 1: /





1

JavaScript (ES6), 106 100 bytes

w=>(P=(a,s)=>a[0]?a.map((_,i)=>P(b=[...a],s+b.splice(i,1))):P[s]=P[s]||++k)[P([...w].sort(),k=''),w]

Casos de prueba

¿Cómo?

P () es nuestra función de permutación recursiva. Pero el objeto que abarca P también se usa para almacenar los rangos de las permutaciones.

P = (a, s) =>               // given an array of letters a[] and a string s
  a[0] ?                    // if a[] is not empty:
    a.map((_, i) =>         //   for each entry at position i in a[]:
      P(                    //     do a recursive call to P() with:
        b = [...a],         //       a copy b[] of a[], with a[i] removed
        s + b.splice(i, 1)  //       the extracted letter appended to s
      )                     //     end of recursive call
    )                       //   end of map()
  :                         // else:
    P[s] = P[s] || ++k      //   if P[s] is not already defined, set it to ++k

El código de ajuste ahora se lee como:

w =>                        // given the input word w
  P[                        // return the permutation rank for w
    P(                      //   initial call to P() with:
      [...w].sort(),        //     the lexicographically sorted letters of w
      k = ''                //     s = k = '' (k is then coerced to a number)
    ),                      //   end of call
    w                       //   actual index used to read P[]
  ]                         // end of access to P[]

1

C ++, 230 bytes

#include<algorithm>
#include<iostream>
#include<string>
using namespace std;void R(string s){int n=1;auto p=s;sort(begin(p),end(p));do if(p==s)cout<<n;while(++n,next_permutation(begin(p),end(p)));}int main(int n,char**a){R(a[1]);}

Según mi pedido, el código definitivamente debe ser ejecutable tal como está. La cláusula de solo función es básicamente basura. : - @

Gracias a quienes amablemente respondieron la pregunta de qué se puede cortar para mí. En interés de válido código , he evitado el popular GCC-ism de incluir <bits / stdc ++. H>, que siempre he considerado una trampa falsa.

Lo que sigue es lo que queda de mi publicación original:


Siempre estoy inseguro cuando uso C y C ++, lo que cuenta para el total de bytes. Según el programa, la función o el fragmento? la respuesta sigue siendo vaga (supongo que siempre que no sea un fragmento). Así que voy con la más corta de las dos posibilidades.

Aquí no tiene los encabezados necesarios, etc.

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

void R( string s )
{
  int n = 1;
  auto p = s;
  sort( begin(p), end(p) );
  do if (p == s) cout << n;
  while (++n, next_permutation( begin(p), end(p) ));
}

int main( int n, char** a )
{
  R( a[1] );
}

Que los campos de golf se reducen a 230 bytes, un tercio de ese estándar requerido por cada programa C ++. (Por lo tanto, no me siento tan mal sin contarlo, pero como nunca he visto una queja firme de ninguna manera, OP tendrá que decirme qué prefiere satisfacer "escriba un código para tomar cualquier palabra como entrada" y mostrar su rango ".)

Tampoco estoy seguro de si esto satisface "el rango debería ser el resultado".


1
Uh ... AFAIK nuestras reglas cuentan necesarias ( using namespace std, #include <algorithm> encabezados utilizados para definir la función en bytes. Y ... No, main(){}es un programa válido de C ++ (g ++) a 8 bytes.
user202729

No estoy tratando de ser un moco obstinado, pero veo presentaciones para C y C ++ (así como otros lenguajes) todo el tiempo que son solo una función. Quiero una respuesta definitiva Por lo general, no juego golf en lenguajes C por esta misma razón. (Y estoy feliz de regolf.)
Dúthomhas

1
Incluso en Python, a import mathmenudo es necesario. Déjame encontrar el meta relevante ...
user202729

@ Dúthomhas Esas soluciones no requieren encabezado incluye. La aritmética básica no requiere encabezado, y algunas funciones pueden declararse y rellenarse implícitamente mediante la vinculación de stdlib (like putsy printf). Su código debe compilarse y ejecutarse correctamente tal cual para que sea válido. Ver: codegolf.meta.stackexchange.com/a/10085/45941
Mego

@Mego Sin declaración de mainfunciones no se puede ejecutar como está.
user202729




0

PowerShell , 275 bytes

param($s)function n($a){if($a-eq1){return}0..($a-1)|%{n($a-1);if($a-eq2){$b.ToString()}$p=($j-$a);[char]$t=$b[$p];for($z=($p+1);$z-lt$j;$z++){$b[($z-1)]=$b[$z]}$b[($z-1)]=$t}}if($s.length-eq1){1;exit}$b=New-Object Text.StringBuilder $s;(n($j=$s.length)|sort -u).indexOf($s)+1

Pruébalo en línea!

Entonces, esto es un desastre sangriento.

PowerShell no tiene ninguna permutaciones incorporada, por lo que este código utiliza el algoritmo de aquí (mucho golf), que está disponible bajo la Licencia pública limitada de Microsoft ( Anexo B en esta página de licencias).

El programa toma la entrada $scomo una cadena, luego el programa real comienza con $b=New-Object .... Estamos construyendo un nuevo objeto StringBuilder , que es (esencialmente) una cadena mutable de caracteres. Esto nos permitirá manejar las permutaciones más fácilmente. Luego llamamos a la función n(configurada $jen el camino para que sea la longitud de la cadena de entrada), sortcon la -umarca nique como salida, tome.indexOf() para encontrar la cadena de entrada y agreguemos 1porque PowerShell está indexado a cero.

La función es la parte principal del programa. Toma como entrada un número, y cada iteración contará hasta que alcancemos1 (es decir, una sola letra). El resto de la función esencialmente llama recursivamente a la función, así como toma la letra actual y la itera en cada posición.

Hay un solo bit de lógica adicional if($s.length-eq1){1;exit}para tener en cuenta las cadenas de entrada de longitud 1debido a cómo funciona la función de permutaciones.


0

Pyt , 5 bytes

ĐᒆỤ≥Ʃ

Explicación:

            Implicit input
Đ           Duplicate input
 ᒆ         Get list of all permutations of input
  Ụ         Get unique permutations
   ≥        Does each permutation come before or is equal to the input?
    Ʃ       Sum of result of previous step (converts booleans to ints)

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.