Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Serapis

#3501
Loop Proc1, te devuelve a Proc1, pero antes decrementa el registro CX en una unidad, cuando CX llega a 0, deja de hacer el salto a Proc1... Entonces se trata de saber que valor ingresas en el registro CX.

Si miramos el código, al registro CX, no se le ha asignado explícitamente ningún valor, luego contendrá la basurilla que reste de otro programa, si más adelante colocas un valor en CL, pero no sabemos cual hay en CH, luego...  :silbar: :silbar: :silbar:

Típicamente un bucle lleva la estructura:

Código (asm) [Seleccionar]
MOV CX, Contador
Inicio:
... codigo a repetir
LOOP Inicio

cuando CX valga 0
...codigo despues del bucle


Prueba a asignar a contador un valor arbitrario cada vez, por ejemplo 13, ejecuta paso a paso y verás como el bucle retorna una y otra vez al 'Inicio', y cólo cuando CX valga 0, ejecuta el código tras el bucle.

Dado que dices "n números ingresados", Contador debería valer ese 'n'. Si 'n' no es conocido, porque se debe ejecutar una y otra vez hasta que el usuario tome una decisión al respecto, entonces el bucle que debe usarse no va por Loop, mejor LOOPNE, o LOOPNZ por ejemplo haciendo que cuando el usuario quiera terminar pulse una determinada tecla, tu haces un TEST entre el valor de la letra esperada (Q) y el valor de la letra introducida por el usuario, y acto seguido saltas en función del resultado del test... a diferencia de otros lenguajes, el ensambalador permite una infinidad de opciones para hacer lo mismo. compruebas si la tecla pulsada es la deseada, en cuyo caso puedes hacer un XOR CX CX (que cambia su contenido a 0, y entonces usas LOOPNZ), cuando CX sea 0, saldrá del bucle... en este caso el salto está condicionado, por la pulsación de una tecla concreta (la 'Q' por ejemplo de "Quit")...
Y tu código quedaría controlado tal que así:

Código (asm) [Seleccionar]
MOV CX, 1 <-- poner un valor en el contador
Inicio:
.... tu codigo (entrada de datos por parte del usuario)
TEST teclaesperada "Q", contra valor entrado
JNE FinOpera <--- SALTAR si igual (o si no cero JNZ)
INC CX
.... tu código para sumar el nuevo valor entrado (distinto de Q)
FinOpera:  <--- punto de salto si usuario pulsa tecla Q (salir)
LOOPNZ Inicio

Al llegar a Loop, si la tecla introducida es distinta de la esperada, se incrementa CX, entonces CX=2, luego Loop decrementa CX, y CX vuelve a valer 1.
En cambio, si el númnero recibido es igual al valor ASCII de Q (81) el test devuelve 'True', y por tanto saltamos el incremento de CX, como vale 1, cuando llegue a LOOP decrementa 1, vale 0 y por tanto sale ya del bucle.

En resumen:
- Fíjate que tu no tienes claro (yo por lo menos leyendo tu código), el valor de CX, así que no hay forma de saber cuando llega a cero...
- LOOP decrementa CX en 1 cada vez que se ejecuta y si CX vale 0, sale fuera del bucle.
- Si el condicional de salida depende de algún factor más, puedes o bien controlar directamente CX (como te muestro en el ejemplo), o bien usar otras variantes de LOOP, LOOPE, LOOPZ, LOOPNE, LOOPNZ, o incluso alguna instrucción condicional de salto... (por ejemplo JNE, podría saltar fuera del bucle directamente, es buena práctica al inicio, tener una única salida de un procedimiento, cuando tengas buen control del código, no te importará que se salga desde más de una parte)...
#3502
No acabo de entender la manía de ciertas empresas de 'matar' tecnología que funciona y funciona bien...
Yo no veo ningún problema en que el 2º, el 5º o el 20º convivan con el 1º.
Es estúpido pretender que solo tiene derecho a 'vivir' el nº 1 en la materia que sea...

Ahí está el "flash", la cosa más burda que parió la informática en cuando a formatos de fichero, y ha vivido incluso épocas de esplendor, cuando nunca debió nacer y ver la luz.
#3503
Claro, si es lo que estoy diciendo... si te pegan un tiro en la calle, la policía (el Microsoft, del ejemplo), echa la culpa al ciudadano, por no llevar un chaleco antibalas...

Y es que una cosa es la culpa y otra muy distinta las consecuencias........ las consecuencias las pagan las empresas, pero la culpa... pués son el último culpable en toda la cadena... igual que en el tiroteo, primero el culpable será el asesino, y el último el ciudadano...

No está bien sacudirse las culpas de encima para echárselas a otro, el que está al final de la cadena bastante tiene con pagar las consecuencias, para que encima le digan que "la culpa es suya"...
#3504
Cita de: wolfbcn en 14 Mayo 2017, 13:06 PM
Desde hace apenas algunas horas, los usuarios de dispositivos móviles Android se están encontrando con que, al descargar Netflix desde la Google Play Store, la tienda de apps lanza un mensaje de error informando de que 'el dispositivo no es compatible'. Un problema relacionado con los dispositivos rooteados y que, en poco tiempo, Netflix ha confirmado.
Ayyy, el maldito dequeísmo...  >:D >:D >:D >:D

"Informando que..."
#3505
Cita de: PalitroqueZ en 14 Mayo 2017, 04:45 AM
pertenecer a la alta gerencia de una empresa va más allá de ganar un sueldazo y aparecer en la sección de sociales del periodico, es un trabajo 24/7/365, porque ...
La responsabilidad de algo (profesional), queda delimitada, por lo que pone en tu contrato, y punto. De hecho si intentas hacer algo más que no está estipulado en tu contrato, es bastante probable que te paren los pies y te recuerden cual es tu puesto.

Lo que los demás quieran poner en tus espaldas, es problema de su imaginación. Tu mochila la define tu contrato.
#3506
Guau...
Esto es como decir que si hay un atraco en un banco y un atracador mata a alguien, la culpa es del muerto, por ir al banco...

La culpa SIEMPRE es del delincuente, en segundo lugar, será culpa de la seguridad del banco, y solo en último lugar, ¿los afectados podrían haber hecho mejor las cosas?, tal vez sí, tal vez no.
#3507
Continuamos...
El segundo algoritmo, es básicamente un esquema de revólver, exactamente tal y como es un cuentakilómetros.

La idea básica detrás de ello, es que hay un bucle por cada carácter. Y ese bucle se encarga de iterar exclusivamente ese carácter, al final del mismo (o antes de entrar) se pone el valor inicial de nuevo (esto es automático en los bucles for, ya que en ellos se declara explícitamente dichos valores de inicio y fin).
En cada bucle, por tanto se establece el valor actual en la posición que ocupa en el término permutado.
Cuando se alcanza el bucle interior, en cada iteración de éste, se obtiene ya la permutación completa.

La ventaja de este algoritmo (genérico), sobre el declarado en el mensaje previo, es que no requiere con cada permutación generar cada vez todos sus caracteres. La forma más clara de visualizar este algorimo, se refleja en un cuentakilómetros...

De este algoritmo expondré tres variaciones, la primera basada en un bucle for.
- La ventaja de éste algoritmo sobre el anterior es la velocidad gracias a evitar, la continua generación de caracteres que no cambia en la siguiente iteración.
- Su desventaja (como bucle for), la dificultad de establecer el punto inicial desde el que comenzar si no es, el comienzo de la permutación. Las variantes posteirores para este algoritmo solventan este problema.

Ahora ya vayamos con el código, para el mismo se ha provisto también una ventana y una clase que realiza el trabajo. Si bien la ventana será la misma para las tres variantes del algoritmo.

Aquí una vista de la interfaz, muy sencilla y el resultado tras la ejecución.


El código de la interfaz, es bien sencillo, básicamente se instancia la clase, y se invoca el método enumerar con los parámetros que aparecen en los textos. En esta versión, no se usa el valor de estado inicial, o dicho de otra manera, el valor de comienzo está fijado al comienzo de la iteración.

Código (vbnet) [Seleccionar]

Public Class frm2 ' la ventana, formulario
   Private buc As New cBucAni ' instancia a la clase usada

   Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
       Dim Min() As Byte, Max() As Byte
       Dim z As Decimal

       Min = StringToByteArray(TextBox2.Text)  ' Valor mínimo: Ejemplo: "AAAAZ"
       Max = StringToByteArray(TextBox3.Text)  ' Valor final, Ejemplo: "ZWZZA

       z = buc.EnumerarFor(Min, Max)
   End Sub

   Private Function StringToByteArray(ByRef Txt As String) As Byte()
       Return System.Text.Encoding.Unicode.GetBytes(Txt)
   End Function
End Class

- El código, primero se crea una instancia de la clase (llamada: "cBucAni", son bucles anidados, no me he complicado con el nombre).
- Luego el código del botón. Primero llama a una función para obtener los bytes (2 bytes por carácter) respectivos a los textos de límite de la enumeración. Luego invoca el método enumerar.
- La función devuelve la cantidad de permutaciones (aunque luego no usamos ese valor para nada). El tipo de datos Decimal, es un tipo de 96bits, + 1 bit de signo... Puede ponerse un tipo de bytes (64bits), después de todo, no es estrictamente necesario devolver la cantidad de permutaciones.

Vayamos con el código de la clase para esta variante del algortimo-B:

Código (vbnet) [Seleccionar]

Public Class cBucAni


   Public Function EnumerarFor(ByRef sMin() As Byte, ByRef sMax() As Byte) As Decimal
       Dim a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p As short  ' 16bits con signo
       Dim Max(0 To 15) As Short
       Dim Min(0 To 15) As Short
       Dim Inc(0 To 15) As Short
       Dim SizeClave As Short  ' Tamaño de las claves (cantidad de caracteres que contienen)
       Dim ClavePermutada() As Byte  ' Clave generada en bytes.

       Dim t As Byte
       Dim z As Decimal, Crono As Single
       Dim txt As String

       Crono = TimeOfDay.Ticks ' ticks desde medianoche hasta la hora actual

       z = CalcularNumPermutaciones(sMin, sMax)
       If (z < 0) Then
           Return -1
           Exit Function
       Else
           SizeClave = sMin.Length
           ReDim ClavePermutada(0 To SizeClave - 1)

           For t = 0 To (SizeClave - 2) Step 2
               Max(n) = sMax(t)
               Min(n) = sMin(t)
               n += 1
           Next
           For t = 0 To n - 1 '((SizeClave \ 2) - 2)
               If (Max(t) > Min(t)) Then
                   Inc(t) = 1
               ElseIf (Max(t) < Min(t)) Then
                   Inc(t) = -1
               End If
           Next

           For t = n To 15 'SizeClave To 15
               Inc(t) = 256
               Min(t) = -1
               Max(t) = -1
           Next

       End If

       For p = Min(15) To Max(15) Step Inc(15)
           If (p >= 0) Then
               ClavePermutada(30) = p
           End If
           For o = Min(14) To Max(14) Step Inc(14)
               If (o >= 0) Then
                   ClavePermutada(28) = o
               End If
               For n = Min(13) To Max(13) Step Inc(13)
                   If (n >= 0) Then
                       ClavePermutada(26) = n
                   End If
                   For m = Min(12) To Max(12) Step Inc(12)
                       If (m >= 0) Then
                           ClavePermutada(24) = m
                       End If
                       For l = Min(11) To Max(11) Step Inc(11)
                           If (l >= 0) Then
                               ClavePermutada(22) = l
                           End If
                           For k = Min(10) To Max(10) Step Inc(10)
                               If (k >= 0) Then
                                   ClavePermutada(20) = k
                               End If
                               For j = Min(9) To Max(9) Step Inc(9)
                                   If (j >= 0) Then
                                       ClavePermutada(18) = j
                                   End If
                                   For i = Min(8) To Max(8) Step Inc(8)
                                       If (i >= 0) Then
                                           ClavePermutada(16) = i
                                       End If
                                       For h = Min(7) To Max(7) Step Inc(7)
                                           If (h >= 0) Then
                                               ClavePermutada(14) = h
                                           End If
                                           For g = Min(6) To Max(6) Step Inc(6)
                                               If (g >= 0) Then
                                                   ClavePermutada(12) = g
                                               End If
                                               For f = Min(5) To Max(5) Step Inc(5)
                                                   If (f >= 0) Then
                                                       ClavePermutada(10) = f
                                                   End If
                                                   For e = Min(4) To Max(4) Step Inc(4)
                                                       If (e >= 0) Then
                                                           ClavePermutada(8) = e
                                                       End If
                                                       For d = Min(3) To Max(3) Step Inc(3)
                                                           If (d >= 0) Then
                                                               ClavePermutada(6) = d
                                                           End If
                                                           For c = Min(2) To Max(2) Step Inc(2)
                                                               If (c >= 0) Then
                                                                   ClavePermutada(4) = c
                                                               End If
                                                               For b = Min(1) To Max(1) Step Inc(1)
                                                                   If (b >= 0) Then
                                                                       ClavePermutada(2) = b
                                                                   End If

                                                                   For a = Min(0) To Max(0) Step Inc(0)
                                                                       ClavePermutada(0) = a
                                                                       ' Usar Permutación desde aquí:
                                                                       'txt = System.Text.Encoding.Unicode.GetString(ClavePermutada)
                                                                       ' call FuncionX(ClavePermutada)
                                                                   Next
                                                               Next
                                                           Next
                                                       Next
                                                   Next
                                               Next
                                           Next
                                       Next
                                   Next
                               Next
                           Next
                       Next
                   Next
               Next
           Next
       Next


       ' Devolver resultados        
       Crono = ((TimeOfDay.Ticks - Crono) / 10000000)  ' ticks hasta la hora actual, menos los de comienzo= ticks invertidos en la tarea.
       txt = System.Text.Encoding.Unicode.GetString(ClavePermutada)
       MessageBox.Show("Tiempo: " & Crono.ToString & vbCrLf & "Permutaciones: " & z.ToString & vbCrLf & "Ultima clave Permutada: " & txt)
       Return z
   End Function

' ....
End Class

Como se ve la clase contiene exclusivamente un metodo (EnumerarFor), que admite dos parámetros. El comienzo de la iteración para cada carácter y el final de iteración para cada carácter.
Una particularidad extra de este algoritmo (en las 3 variantes), es que se ha modificado la forma del alfabeto que utiliza (ya vimos en el algoritmo previo diferentes formas de expresar un alfabeto). Con sólo esos dos parámetros, en realidad estamos definiendo un alfabeto exclusivo para cada carácter, además de dejar claro, el largo de las claves que se van a generar (tan largas como caracteres tienen ambos parámetros. De hecho es requisito que ambos parámetros sean igual de largos.
Esto hace popsible que si deseamos generar claves en la forma:
 AAAA-000-xx:QQQQ
 ZZZZ-999-pp:DDDD
Puede entenderse que para los 4 primeros caracteres (a la izquierda), el rango del alfabeto está en: A-Z, luego viene un guión fijo, los dos siguientes caracteres fijan su alfabeto al rango x-p, el siguiente carácter está fijo al carácter ":" y los 4 últimos caracteres usan un alfabeto en el rango Q-D (nótese que es decreciente)...

Partiendo de esta funcionalidad, es fácil deducir, otra donde delimitamos la entrada de un texto circunscrito a determinado rango de valores, para cada carácter y declaramos no válidos el resto.

Esto facilita enormemente la definición de alfabetos para cada carácter, al no exigir explicítamente un array por cada carácter, y en cuanto al código, implementar esto en el algoritmo, del mensaje previo (el definido como algoritmo A), sería complejo y la cantidad de comparaciones para delimitarlo, lo harían extremadamente lento, en éste en cambio, no existe penalización alguna (salvo una verificación inicial prácticamente sin coste en realción al tiempo empleado en la enumeración) ni exige arrays de alfabetos...
Eso sí, la definición de este alfabeto, establece el orden ASCII, es decir si definimos un inicion y fin como:
  00000000
  ZZZZZZZ
En realidad estamos definiendo un rango entre los caracteres ASCII '0' y 'Z', no del 0-9 y A-Z... y justamente se suceden en el orden en que aparecen en el ASCII... si no fuera el caso, sería necesario un Array que defina los caracteres y el orden que ocupan (o varios si cada carácter tuviera su propia evolución).

- Tras acceder a la enumeración, lo primero es contar las permutaciones resultantes, y una verificación de validez de los parámetros. Para ello se invoca una función que está en un módulo privado del proyecto pero común a todo el proyecto. Se explica más abajo dicha función, aquí baste decir que si los parámetros no son consecuentes, devuelve un valor negativo que fuerza la salida de la función y que debe interpretarse como error...

- Luego se genera un array de bytes (2  por cada carácter) del mismo tamamo que los parámetros, que será donde se deposite el resultado de la enumeración... y que se irá sobrescribiendo una y otra vez...

- Lo siguiente es establecer los valores adecuados para el inicio, final del bucle y dirección de avance (puede ir tanto desde A-Z, como desde Z-A, por tanto el bucle puede aumentar o reducir en unidades.

- Lo siguiente, si se mira bien, es que hay 16 bucles, esto implica que con la misma función, sin cambios, podríamos generar claves de largo entre 1 y 16. Las claves se generan en los bucles más internos, y quedan sin usar los bucles más externos, para estos se fijan Min, Max e Incremento a valores que hacen que el bucle se ejecute una sola vez y por tanto no alteran ni se cae en errores.

- Finalmente vienen los bucles, extreamadamente sencillos y que puede verse cómo actúan exactamente como los cuentakilómetros.
Se ha recurrido a señalar cada bucle, como a,b,c,d,e...p, el bucle 'a', es el más interno y sobre la clave produce el carácter 0, el más externo (el bulce 'p'), produce el último carácter (si usan claves de 16 caracteres.


A continuación adjunto el código de la función que se invoca a al entrada de la función enumerar... y que tiene por objeto contar el número de permutaciones que se van a generar y verificar un par de cosas: que ambos parámetros tienen el mismo tamaño de caracteres (podría añadirse una verificación de delimitación del tamaño mínimo (1) y máximo (16) caracteres, que no se realiza), puede ocurrir un error si el número de permutaciones sobrepasa el rango de 96 bits (12 bytes, pués se ha declarado la cuenta con un tipo de datos
Decimal). Nótese que los bucles no generarán error por desbordamiento, opera simplemente con 8 y 16 bits (byte y short) y el tamaño, simplemente es tiempo que tarda. Si se prefiere evitardesbordamiento incluso para 96 bits, puede omitirse la cuenta de permutaciones y devolverlo en formato de string en la forma X a la Y (26^7), (36^5), (256^16), etc...

Código (vbnet) [Seleccionar]

''' <summary>
   ''' Calcula el número de permutaciones totales.
   ''' </summary>
   ''' <param name="Min">Define el valor mínimo para cada carácter.</param>
   ''' <param name="Max">Define el valor máximo para cada carácter.</param>
   ''' <returns>El número de permutaciones totales. Un valor negativo, si hubo errores.</returns>
   ''' <remarks>Cada carácter tiene su propio alfabeto, circunscrito al rango Min-Max, para el índice que ocupa.</remarks>
   Friend Function CalcularNumPermutaciones(ByRef Min() As Byte, ByRef Max() As Byte) As Decimal
       Dim k As Short, j As Short, n As Decimal, v As Short

       k = Min.Length
       If (k <> Max.Length) Then
           MsgBox("Los 2 arrays deben ser del mismo tamaño: Min y Max.")
           Return -2
           Exit Function
       End If

       Try
           n = 1
           For j = 0 To k - 2 Step 2
               v = Max(j) ' impide que la resta entre dos bytes (a continuación), de error por desbordamiento, si el resultado es menor de 0.
               v = (v - Min(j))
               n = (n * (Math.Abs(v) + 1)) ' ABS= Valor absooluto del número (esto es, ignora el signo y lo toma como positivo).
           Next

           Return n
       Catch ' de ocurrir un error se espera que sea desbordamiento... (de n).
           Return -1
       End Try
   End Function



Finalmente comentar que el código (el del algoritmo de permutación, no esta última función), pero resuelve el caso y es más rápido que el algortimo presentado anteriormente (en el mensaje previo), en contra tiene que no es cómodo establecer un punto de inicio distinto al inicio de las permutaciones, y también que el código no es muy elegante.

Y eso es todo por hoy...

En el próximo mensaje proveeré una variante que resuelve ambas cosas a costa de una pérdida de eficiencia en velocidad, debida a que recurro a un modelo recursivo, frente a este iterativo, además la recursividad será sobre una clase, no sobre un método.

---------------------
p.d.: Un tick en NET es la diezmillonésima parte de 1 sg. por ello al final se divide entre 10 millones, para tener el tiempo en segundos.
#3508
Cabe preguntarse si los hackers de esas extorsiones no serían personal propio del FBI, razón por la cual, tendría sentido recomendar el pago de los rescates...
#3509
Creo que es innecesario.
Básicamente porque son dos filosofías reñidas entre sí. Y lo que unos usuarios quieren lo encuentran en lo que eligen, si quisierna lo otro, se pasarían al otro sistema o viceversa...

Probablemente seremos los programadores, los más beneficiados del asunto, pero los usuarios creo que no tanto, por no decir prácticamente nada.
#3510
Un poco exagerado...
Vale que lo hizo deliberadamente, y por ello ciertamente implica una falta de respeto, pero...
Yo creo que un par de collejas y a lo sumo una semana de cárcel, sobraba como escarmiento.