/tech/ - Tech 2.0

Mode: Reply
Name
Subject
Message

Max message length: 4096

Opciones
Files
E-mail
Password

(used to delete files and postings)

Misc

Remember to follow the rules


FizzBuzz Thread Choroy 11/19/2025 (Wed) 00:39:43 bc2536 No. 18612
Postea tu fizzbuzz #include [orange]stdio.h> #include [orange]stdlib.h> int main(int argc, char* argv[]) { int j, k, n; const char s[] = { 0x25, 0x64, 0x0a, 0x00, 0x46, 0x69, 0x7a, 0x7a, 0x0a, 0x00, 0x42, 0x75, 0x7a, 0x7a, 0x0a, 0x00, 0x46, 0x69, 0x7a, 0x7a, 0x42, 0x75, 0x7a, 0x7a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x04, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00 }; if (argc == 2) { n = atoi(argv[1]); for (j = k = 1; j [orange]= n; j++) { printf(s + s[26 + k++], j); if (k == 0x10) k = 1; } } return 0; }
>>18612 for i in range(101): if i % 3 0 and i % 5 0: print("FizzBuzz") elif i % 3 == 0: print("Fizz") elif i % 5 == 0: print("Buzz") else: print(num)
>>18613 >el IB cambió los == a TEXTO ROJO Jajié. Usa [code].
0 and i % 5
fn main() { for i in 1..=100 { match (i % 3, i % 5) { (0, 0) => println!("FizzBuzz"), (0, _) => println!("Fizz"), (_, 0) => println!("Buzz"), (_, _) => println!("{}", i), } } }
>>18616 excelente
>>18612 una duda de noob, para que se usan valores en hexadecimal?
>>18620 para editar los saves del re3
>>18620 para editar los saves del re3
>>18620 Los valores en hexa se usan típicamente para escribir números que representan el valor exacto en la memoria del computador. Recordemos que en la memoria de los computadores modernos la data se guarda en bytes, los cuales son grupos de 8 bits, o sea puede guardar 256 valores distintos. Una opción sería escribir estos números como decimal, pero esto llevaría a que cada número tuviera un largo de texto distinto (de 1 a 3 dígitos). En el sistema hexadecimal cada dígito cuenta hasta 16, por lo que dos hexas son 16*16 = 256, justo la misma cantidad que un byte. Entonces con dos hexas puedes escribir precisamente la misma cantidad que en un byte, con cuatro hexas lo mismo que un half word de 16 bits y así consecutivamente. Me tinca que esto viene de los tiempos antiguos cuando los computadores tenían poca capacidad de entregar información por lo que era necesario ser súper eficiente con lo que imprimías. Ahora ya no tenemos esas limitaciones, pero en nuestras mentes sigue la idea de que hexa significa que representa los bytes exactos en memoria, mientras que dígitos en decimal son números de uso humano. Como el string en el código de OP contiene valores que no tienen un carácter imprimible asociado (sus 0x00, 0x04 y 0x10) entonces la forma más limpia es usar hex. Ahora, si me preguntas a mí, creo que el que escribió ese código lo hizo pa' puro dárselas de encachado, si analizamos el string nos damos cuenta que en verdad representa 4 strings distintos ("%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n") y que los últimos 15 caracteres en verdad son un índice a cual de los 4 strings anteriores usar. De hecho yo consideraría sucio mezclar ambos datos en un único string, pero bueno, seguramente lo escribieron así para dárselas de old school hacker e impresionar a los que no saben C.
>>18620 Para dársela de macanudo pero es c++ Eso lo único que hace es gastar líneas de codigo
>>18612 Buen trabajo, un algoritmo muy bello >>18623 Si no sabes sencillamente aceptalo, pero no tires un wall text por las puras weas >>18624 Compila perfectamente en C
>>18620 >>18620 El hex aquí solo es estético (para darle el toque de chino), el algoritmo funciona perfectamente sin hex con enteros. No es como dicen los anones que es para creerse hacker, o weas por el estilo. El algoritmo es bello por si mismo, aún sin usar hex. #include [orange]stdio.h> int main() { int j, k, n; // const char s[] = { // 0x25, 0x64, 0x0a, 0x00, 0x46, 0x69, 0x7a, 0x7a, // 0x0a, 0x00, 0x42, 0x75, 0x7a, 0x7a, 0x0a, 0x00, // 0x46, 0x69, 0x7a, 0x7a, 0x42, 0x75, 0x7a, 0x7a, // 0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a, // 0x04, 0x00, 0x00, 0x04, 0x0a, 0x00, 0x04, 0x00, // 0x00, 0x10, 0x00 // }; const char s[] = { '%', 'd', '\n', '\0', // 0-3 'F', 'i', 'z', 'z', '\n', '\0', // 4-9 'B', 'u', 'z', 'z', '\n', '\0', // 10-15 'F', 'i', 'z', 'z', 'B', 'u', 'z', 'z', '\n', '\0', // 16-25 // s[26]–s[42]: ciclo FizzBuzz codificado como offsets 0, // "%d\n" (1) 0, // "%d\n" (2) 0, // "%d\n" (3) 4, // "Fizz\n" (4) 0, // "%d\n" (5) 10, // "Buzz\n" (6) 4, // "Fizz\n" (7) 0, // "%d\n" (8) 0, // "%d\n" (9) 4, // "Fizz\n" (10) 10, // "Buzz\n" (11) 0, // "%d\n" (12) 4, // "Fizz\n" (13) 0, // "%d\n" (14) 0, // "%d\n" (15) 16, // "FizzBuzz\n" (16) 0 // "%d\n" (17 → relleno) }; n = 100; for (j = k = 1; j [orange]= n; j++) { // https://www.it.uc3m.es/pbasanta/asng/course_notes/input_output_printf_es.html // s + s[26 + k++]: parámetro format // j: valor para los argumentos que tiene un 'conversion directive' (%d) // https://man.openbsd.org/printf.3 printf(s + s[26 + k++], j); // Reinicia el cilo de 16 if (k == 16) k = 1; } return 0; } Removí todo lo referente a argumentos. Reescribí el vector s con los equivalentes en ascii y enteros, lo puedes probar en un compilador online: https://www.onlinegdb.com/online_c_compiler Básicamente lo que se hizo en el vector s es apilar datos. En ram siempre tienes datos apilados, no es nada nuevo, salvo porque a los programadores ahora les enseñan a usar variables separadas para todo. Podríamos decir que se ahorran algunos bytes en este caso respecto a la definición de las propias estructuras. Pero podrías usar un vector auxiliar para la tabla de offsets. El ciclo de 16 que lleva k sobre j en el mismo for, tiene que ver sobre el reto fizz buzz: - Para cada múltiplo de 3 imprimes fizz - Para cada múltiplo de 5 imprimes buzz - Para cada múltiplo de ambos, osea de 3 * 5 (15)... Así configuras los primeros 16 valores del ciclo repetitivo, porque en la recta numérica la aparición de los múltiplos 3, 5 y 15 es determinista, es decir que sus posiciones no cambian. Sobre las estructuras en los vectores de char en c Cada elemento se termina con un caracter nulo \0 o 0x00, por lo que un vector o arreglo de chars puede tener múltiples textos adentro, y los reconoces por sus posiciones de inicio y 0x00 al final. Para imprimir un vector harías normalmente algo como esto: const char v[] = { 'h', 'o', 'l', 'a', '\n', '\0' }; printf( "%s", v ); Pero si tuvieras esto, printf solo imprimiría hola const char v[] = { 'h', 'o', 'l', 'a', '\n', '\0', 'm', 'u', 'n', 'd', 'o', '\0' }; printf( "%s", v ); Para imprimir mundo deberías entregarle un offset con aritmetica de punteros const char v[] = { 'h', 'o', 'l', 'a', '\n', '\0', 'm', 'u', 'n', 'd', 'o', '\0' }; printf( "%s", v + 6 );
>>18627 >>18627 Acá esta la belleza y el ingenio del algoritmo. El for cuena en j de 1 hasta el número que tu quieras. Yo le puse 100. K lleva siempre el ciclo de 16 de los 16 elementos de la tabla de offsets. Y Son 16 porque en el número 15 empieza el primer múltiplo de 3 * 5. A partir de aquí el ciclo se repite iterativamente de 15 en 15 manteniendo las mismas posiciones para todos los múltiplos (la gracia de base 10 (decimal) ). No tiene nada que ver con hexadecimal. 0, // "%d\n" (1) 0, // "%d\n" (2) 0, // "%d\n" (3) 4, // "Fizz\n" (4) 0, // "%d\n" (5) 10, // "Buzz\n" (6) 4, // "Fizz\n" (7) 0, // "%d\n" (8) 0, // "%d\n" (9) 4, // "Fizz\n" (10) 10, // "Buzz\n" (11) 0, // "%d\n" (12) 4, // "Fizz\n" (13) 0, // "%d\n" (14) 0, // "%d\n" (15) 16, // "FizzBuzz\n" (16) 0 // "%d\n" (17 → relleno) Entonces lo lindo de esto, es que k tiene un offset de 26, lo que te deja en el elemento (1) de la tabla de offsets. De manera que siempre recorras las secuencia de elementos a imprimir. Para imprimir un número que no es múltiplo en el reto, printf se configura así dinámicamente printf( "%d\n", j ); Pero para imprimir los múltiplos del reto printf se configura así printf( s + s[26 + k++], j ); La única pifea que te comes al no usar if, es que en la segunda configuración del printf, j está demás ya que no tienes el "conversion directive" para indicar que ahí deberá ser reemplazada una variable. s le dice a printf que se imprimirá un vector, que va a su posición 0, luego "+ s[26 + k++]" te da la aritmética de punteros, moviéndote dentro de tu vector 26 posiciones + k a partir del 0 inicial, puesto que en c, cualquier vector es en realidad un puntero a memoria. Finalmente k++ incrementa k en 1. De esa manera recorres la secuencia iterativamente de 15 en 15 o de 16 en 16 dependiendo de como lo quieras mirar (porque j empieza en 1 y no en 0). El if solo reinicia en un punto, y 16 solo es dicho punto (coincidencia). Pero en realidad solo te mueves entre 0 y 25 (en los índices de s), gracias a los índices almacenados en la tabla de offsets contigua (la de arriba). Así, te ahorras hacer los if, definir variables extras, y de paso demuestras tu experiencia en c. El elemento 17 de la tabla de offsets le indica a c que ahi termina el vector, si no estuviera te podrías pasar mas allá y accesar a memoria no inicializada o de otra parte, pero en este caso que es controlado, creo que es omitible.
>>18626 >Si no sabes sencillamente aceptalo, pero no tires un wall text por las puras weas Hueón barsa. Mi primer párrafo es una explicación histórica de por qué se usa hex en general en la disciplina de la programación (¿tiene algún error? Pues dígalo). El segundo párrafo es una explicación del array mucho más concisa que los dos posts de verborrea innecesaria que te mandaste después. El burro hablando de orejas.
>>18630 ya, deja de llorar y estudiate la wea, que si no explico con manzanitas, nunca lo ibas a entender, aer llegas a ver tu peguita de 3 palitos culiao ignorante
mira men te explico:
>>18626 Me estás weando y tiene ventajas escribir así? Osea ponte tu que tengo una placa de desarrollo y no quiero gastar tanta memoria, funcionaria mejor? Cuatico igual
>>18642 Por sí mismo no haría diferencia, por ejemplo: char array1[] = "hola"; char array2[] = {0x68, 0x6F, 0x6C, 0x61, 0x00}; Compilados, array1 y array2 ocupan exactamente el mismo espacio en memoria.
>>18642 Ventajas en sí mismo no diría que tiene, pero sí hay situaciones donde es más fácil y por lo tanto más común resolverlos usando hex. Por ejemplo, en bajo nivel / sistemas operativos / drivers / sistemas embebidos, es común que tengas que escribir bytes específicos en zonas de memoria específicas, en esos casos es común ver que en el código todos esos bytes siempre se escriben en hex.
>>18642 depende del contexto, cuando usas mascaras claramente es ventajoso saber que bytes estan encendidos y cuales apagados: ej: 0xFF00FF00 Si usaras el equivalente entero 4278255360 no sabrías reconcer a simple vista los bytes encendidos. Se usa mucho en exploits para reescribir la pila en buffers overflow, un ej: buf = 'B' * target['Rets'][0] buf [blue] "\x68\x76\x76\x76\x76"*9 # PUSH 76767676 x 9 buf [blue] "\x68\x7f\x7f\x7f\x7f" # PUSH 7F7F7F7F buf [blue] "\x57" # PUSH EDI buf [blue] "\x58" # POP EAX buf [blue] "\x32\x64\x24\x24" # XOR AH,BYTE PTR SS:[ESP+24] buf [blue] "\x32\x24\x24" # XOR AH,BYTE PTR SS:[ESP] buf [blue] "\x48"*150 # DEC EAX x 150 buf [blue] "\x50\x50" # PUSH EAX x 2 buf [blue] "\x53" # PUSH EBX buf [blue] "\x58" # POP EAX buf [blue] "\x51" # PUSH ECX buf [blue] "\x32\x24\x24" # XOR AH,BYTE PTR SS:[ESP] buf [blue] "\x6a\x7f" # PUSH 7F buf [blue] "\x5e" # POP ESI buf [blue] "\x46"*37 # INC ESI buf [blue] "\x56"*10 # PUSH ESI buf [blue] "\x32\x44\x24\x24" # XOR AL,BYTE PTR SS:[ESP+24] buf [blue] "\x49\x49" # DEC ECX buf [blue] "\x31\x48\x34" # XOR DWORD PTR DS:[EAX+34],ECX buf [blue] "\x58"*11 # POP EAX buf [blue] "\x42"*66 buf [blue] "\x3c"*4 buf [blue] "\x42"*48 Tambien lo puedes usar para definir flags #define FLAG_READ 0x01 // 0000 0001 #define FLAG_WRITE 0x02 // 0000 0010 #define FLAG_EXEC 0x04 // 0000 0100 #define FLAG_HIDDEN 0x08 // 0000 1000

Delete
Report