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