remarks cref c# string algorithm iterator

cref - remarks c#



¿Cuál es una buena manera de descubrir todas las palabras posibles de una longitud determinada? (12)

Siempre existe la implementación obligatoria de LINQ. Es muy probable que se trate de basura, pero ¿desde cuándo se interpuso el rendimiento en el uso de nuevas funciones geniales?

var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(); var sequence = from one in letters from two in letters from three in letters from four in letters orderby one, two, three, four select new string(new[] { one, two, three, four });

''secuencia'' ahora será un IQueryable que contiene AAAA a ZZZZ.

Editar:

Ok, entonces me molestaba que fuera posible hacer una secuencia de longitud configurable con un alfabeto configurable usando LINQ. Asi que aqui esta. De nuevo, completamente inútil, pero me estaba molestando.

public void Nonsense() { var letters = new[]{"A","B","C","D","E","F", "G","H","I","J","K","L", "M","N","O","P","Q","R","S", "T","U","V","W","X","Y","Z"}; foreach (var val in Sequence(letters, 4)) Console.WriteLine(val); } private IQueryable<string> Sequence(string[] alphabet, int size) { // create the first level var sequence = alphabet.AsQueryable(); // add each subsequent level for (var i = 1; i < size; i++) sequence = AddLevel(sequence, alphabet); return from value in sequence orderby value select value; } private IQueryable<string> AddLevel(IQueryable<string> current, string[] characters) { return from one in current from character in characters select one + character; }

La llamada al método Sequence produce la misma lista AAAA a ZZZZ que antes, pero ahora puede cambiar el diccionario utilizado y la duración de las palabras producidas.

Estoy intentando crear un algoritmo en C # que produce las siguientes cadenas de salida:

AAAA AAAB AAAC ...and so on... ZZZX ZZZY ZZZZ

Cuál es la mejor manera de lograr esto?

public static IEnumerable<string> GetWords() { //Perform algorithm yield return word; }


javascript!

var chars = 4, abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", top = 1, fact = []; for (i = 0; i < chars; i++) { fact.unshift(top); top *= abc.length; } for (i = 0; i < top; i++) { for (j = 0; j < chars; j++) document.write(abc[Math.floor(i/fact[j]) % abc.length]); document.write("<br />/n"); }


¡Pitón!

(Esto es solo un truco, no me tomes demasiado en serio :-)

# Convert a number to the base 26 using [A-Z] as the cyphers def itoa26(n): array = [] while n: lowestDigit = n % 26 array.append(chr(lowestDigit + ord(''A''))) n /= 26 array.reverse() return ''''.join(array) def generateSequences(nChars): for n in xrange(26**nChars): string = itoa26(n) yield ''A''*(nChars - len(string)) + string for string in generateSequences(3): print string


GNU Bash!

{a..z}{a..z}{a..z}{a..z}


Inspirado por la respuesta de Garry Shutler, decidí recodificar su respuesta en T-SQL.

Diga "Cartas" es una tabla con un solo campo, MyChar, un CHAR (1). Tiene 26 filas, cada una una letra del alfabeto. Entonces tendríamos (puedes copiar y pegar este código en SQL Server y ejecutarlo tal como está para verlo en acción):

DECLARE @Letters TABLE ( MyChar CHAR(1) PRIMARY KEY ) DECLARE @N INT SET @N=0 WHILE @N<26 BEGIN INSERT @Letters (MyChar) VALUES ( CHAR( @N + 65) ) SET @N = @N + 1 END -- SELECT * FROM @Letters ORDER BY 1 SELECT A.MyChar, B.MyChar, C.MyChar, D.MyChar FROM @Letters A, Letters B, Letters C, Letters D ORDER BY 1,2,3,4

Las ventajas son: es fácilmente extensible al uso de mayúsculas / minúsculas, o el uso de caracteres latinos no ingleses (piense en "Ñ" o cedille, eszets y similares) y todavía obtendrá un conjunto ordenado, solo necesita agregar una colación . Además SQL Server ejecutará esto un poco más rápido que LINQ en una sola máquina central, en multinúcleo (o multiprocesadores) la ejecución puede ser en paralelo, obteniendo aún más impulso.

Desafortunadamente, está estancado para el caso específico de 4 letras. La solución recursiva de lassevk es más general, tratar de hacer una solución general en T-SQL implicaría necesariamente SQL dinámico con todos sus peligros.


Solo un comentario para Garry Shutler, pero quiero colorear el código:

Realmente no es necesario hacerlo IQuaryable, ni el tipo, por lo que puede eliminar el segundo método. Un paso adelante es usar Agregado para el producto cruzado, que termina así:

IEnumerable<string> letters = new[]{ "A","B","C","D","E","F", "G","H","I","J","K","L", "M","N","O","P","Q","R","S", "T","U","V","W","X","Y","Z"}; var result = Enumerable.Range(0, 4) .Aggregate(letters, (curr, i) => curr.SelectMany(s => letters, (s, c) => s + c)); foreach (var val in result) Console.WriteLine(val);

¡Anders debería obtener un premio Nobel por la cosa de Linq!


Use algo que automáticamente utilice Google para cada combinación de letras, luego vea si hay más aciertos ".sz" o ".af" y luego ".com" en los primeros cinco resultados ...;)

En serio, lo que estás buscando podría ser Tries (estructura de datos), aunque todavía necesites poblar lo que probablemente sea mucho más difícil ...


¡Haskell!

replicateM 4 [''A''..''Z'']

¡Rubí!

(''A''*4..''Z''*4).to_a


Simpler Python!

def getWords(length=3): if length == 0: raise StopIteration for letter in ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'': if length == 1: yield letter else: for partialWord in getWords(length-1): yield letter+partialWord


Esta es una versión recursiva de las mismas funciones en C #:

using System; using System.Collections.Generic; using System.Text; using System.IO; namespace ConsoleApplication1Test { class Program { static char[] my_func( char[] my_chars, int level) { if (level > 1) my_func(my_chars, level - 1); my_chars[(my_chars.Length - level)]++; if (my_chars[(my_chars.Length - level)] == (''Z'' + 1)) { my_chars[(my_chars.Length - level)] = ''A''; return my_chars; } else { Console.Out.WriteLine(my_chars); return my_func(my_chars, level); } } static void Main(string[] args) { char[] text = { ''A'', ''A'', ''A'', ''A'' }; my_func(text,text.Length); Console.ReadKey(); } } }

Imprime desde AAAA hasta ZZZZ


bueno, si la longitud es una constante 4, entonces esto lo manejaría:

public static IEnumerable<String> GetWords() { for (Char c1 = ''A''; c1 <= ''Z''; c1++) { for (Char c2 = ''A''; c2 <= ''Z''; c2++) { for (Char c3 = ''A''; c3 <= ''Z''; c3++) { for (Char c4 = ''A''; c4 <= ''Z''; c4++) { yield return "" + c1 + c2 + c3 + c4; } } } } }

si la longitud es un parámetro, esta solución recursiva lo manejaría:

public static IEnumerable<String> GetWords(Int32 length) { if (length <= 0) yield break; for (Char c = ''A''; c <= ''Z''; c++) { if (length > 1) { foreach (String restWord in GetWords(length - 1)) yield return c + restWord; } else yield return "" + c; } }


Un código muy simple pero impresionante que genera todas las palabras de 3 y 4 letras del idioma inglés

#include <iostream> using namespace std; char alpha[26]={''a'',''b'',''c'',''d'',''e'',''f'',''g'',''h'',''i'',''j'',''k'',''l'',''m'',''n'',''o'',''p'',''q'',''r'',''s'',''t'',''u'',''v'',''w'',''x'',''y'',''z''} int main() { int num; cin >> num; if (num == 3) { //all 3 letter words for (int i = 0; i <= 25; i++) { for (int o = 0; o <= 25; o++) { for (int p = 0; p <= 25; p++) { cout << alpha[i] << alpha[o] << alpha[p] << " "; } } } } else if (num == 4) { //all 4 letter words for (int i = 0; i <= 25; i++) { for (int o = 0; o <= 25; o++) { for (int p = 0; p <= 25; p++) { for (int q = 0; q <= 25; q++) { cout << alpha[i] << alpha[o] << alpha[p] << alpha[q] << " "; } } } } } else { cout << "Not more than 4"; //it will take more than 2 hours for generating all 5 letter words } }