Ir al contenido


Foto

Generar números y letras Aleatorios


  • Por favor identifícate para responder
31 respuestas en este tema

#1 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 diciembre 2015 - 09:24

Muy buenas días con todos, Antes que nada les deseo que pasen unas bonitas Fiestas Navideñas  :)  :) 

 

Ahora paso al problem... resulta que estoy buscando la forma de como obtener cifras aleatorias de 5 caracteres (letras+números) separados por un guión "-" el resultado final quisiera que fuera así:

7FV89-VE65V-D18V4-AF1A3-S42FA

 

 

En la búsqueda de una solución he aprendido estos métodos:

 

Para obtener un número aleatorio simple:


php
  1. var key1: integer;
  2. Randomize;  // necesario para iniciar el azar
  3. Key1:=random(100);    //  elegimos un num aleatorio cualquiera de 1-100
  4. showmessage(inttostr(key1));   // mostramos el resultado

Para obtener un rango de números aleatorios:


php
  1. uses
  2. . . . , math;
  3.  
  4. procedure TForm1.Button1Click(Sender: TObject);
  5. var key1: integer;
  6. begin
  7. Randomize;  // necesario para iniciar el azar
  8. Key1:=RandomRange(100, 105);    //  // el resultado será desde 100 hasta 105
  9. showmessage(inttostr(key1));   // mostramos el resultado

También les comento que logré crear un generador pero sólo con números, de momento me funciona y es así:

 


php
  1. procedure TForm1.Button6Click(Sender: TObject);
  2. var i, key1, key2, key3, key4, key5 : integer;
  3. begin
  4. Randomize;
  5. key1:=RandomRange(10000, 99999);
  6. key2:=RandomRange(10000, 99999);
  7. key3:=RandomRange(10000, 99999);
  8. key4:=RandomRange(10000, 99999);
  9. key5:=RandomRange(10000, 99999);
  10. Edit1.Text:=inttostr(key1)+'-'+inttostr(key2)+'-'+inttostr(key3)+'-'+inttostr(key4)+'-'+inttostr(key5);

El resultado es así:     57740-29098-10690-25573-14420

Lo cual es algo próximo a lo que busco, pero como les vuelvo a repetir necesito que sean números + letras.

Acudo a su ayuda amigos.....

 


  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 09:45

Hola

 

Si no fuese un formato fijo de 5 cada sector, podrías utilizar el GUID por ejemplo ['{BD0AF488-223B-4B93-BD79-42F0948FB681}']

 

Por lo que yo utilizaría tu idea pero con números hexadecimales, algo así:


delphi
  1. begin
  2. Randomize;
  3. key1:=RandomRange(65536, 1048575);
  4. key2:=RandomRange(65536, 1048575);
  5. key3:=RandomRange(65536, 1048575);
  6. key4:=RandomRange(65536, 1048575);
  7. key5:=RandomRange(65536, 1048575);
  8. Edit1.Text := IntToHex(key1,5) + '-' + IntToHex(key2,5) + '-' +
  9. IntToHex(key3,5) + '-' + IntToHex(key4,5) + '-' + IntToHex(key5,5);
  10. end;

Y utlizo el rango (65536, 1048575) para que tenga los 5 caracteres que se requieren y sin ceros a la izquierda. En hexadecimal tomarían los valores (10000,FFFFF).

 

Saludos


  • 0

#3 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 diciembre 2015 - 10:14

Muchas gracias Egostar por su respuesta, es una buena idea  los GUID no lo había pensado...

también he probado su idea y es muy buena,de momento he logrado obtener los siguientes resultados:

 

79061-B454B-3C981-232BA-583B0

B3F08-DB9D0-D50D8-D23EB-3C54F

F4BC3-DA684-F7C3D-336F6-75593

 

claro que he tenido que cambiar este valor para que funcione:


php
  1. var key1, key2, key3, key4, key5 : integer;   // antes era string

Tambien veo que las letras Hexadecimales van desde A hasta F.

Aún así es muy buen código :) , mas si no fuera mucha molestía quisiera saber más formas de poderlo realizar la primera incognita...


  • 0

#4 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 10:23

Aún así es muy buen código :) , mas si no fuera mucha molestía quisiera saber más formas de poderlo realizar la primera incognita...

 

Para crear los GUID es muy fácil. Con éste código lo haces.

 


delphi
  1. var
  2. MiGuid : TGUID;
  3. begin
  4. if CreateGUID(MiGuid) <> 0 then
  5. Edit1.Text := 'No se pudo crear GUID'
  6. else
  7. Edit1.Text := GUIDToString(MiGuid);
  8. end;

Saludos

  • 0

#5 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 diciembre 2015 - 11:23

Gracias de nuevo Egostar lo he probado y funciona a la primera :) :)

en las pruebas me da estos resultados:

 

{6AE82E58-EB3D-4DA1-AA1E-DD730A9B4FFB}
{77A563B8-FEBD-419A-BD5E-2FF7B23E60A4}
{65B4D693-5AEE-40AF-BBF6-B6B2F595754E}

 

Ahora para poder quitarles los corchetes lo estoy usando de esta forma (por favor corregirme si esta mal):


php
  1. procedure TForm1.Button4Click(Sender: TObject);
  2.   var
  3.     MiGuid : TGUID;
  4.     texto: string;
  5.   begin
  6.     if CreateGUID(MiGuid) <> 0 then
  7.        Edit1.Text := 'No se pudo crear GUID'
  8.     else
  9.        texto:=GUIDToString(MiGuid);
  10.        texto:=AnsiMidStr(texto,2,Length(texto));
  11.        Texto:=Copy(Texto, 0, Length(Texto)-1);
  12.      Edit1.Text := texto;
  13.   end;

EL RESULTADO ES:

61986F2D-6590-4EF1-8658-4207F11AB4B7
C11CD312-7444-4DE7-9BC8-EF7E214DC542
16FA609E-7F56-4966-A93A-07C5094643E0

 

 

Es una buena manera de poder obtener códigos al azar, los voy a guardar para tenerlos en cuenta. 


  • 0

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 11:30

Hoy me encuentro buenito, dejo aquí un código de ejemplo de como llegar a lo mismo de otra forma y que incluso permite indicar la cantidad de claves, su longitud y el separador.


php
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8. Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12. { TForm1 }
  13.  
  14. TForm1 = class(TForm)
  15. Button1: TButton;
  16. Button2: TButton;
  17. Edit1: TEdit;
  18. procedure Button1Click(Sender: TObject);
  19. procedure Button2Click(Sender: TObject);
  20. private
  21. { private declarations }
  22. function RandomStringsKeys(KeysCount, KeysLength: integer; Separator: char = '-'): string;
  23. public
  24. { public declarations }
  25. end;
  26.  
  27. var
  28. Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. procedure TForm1.Button1Click(Sender: TObject);
  37. begin
  38. Edit1.Text := RandomStringsKeys(5, 5);
  39.  
  40. procedure TForm1.Button2Click(Sender: TObject);
  41. begin
  42. Edit1.Text := RandomStringsKeys(4, 5, '#');
  43.  
  44. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  45. Separator: char): string;
  46. const
  47. CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  48. var k, l: integer;
  49. begin
  50. result := '';
  51. for k := 1 to KeysCount do
  52. begin
  53. for l := 1 to KeysLength do
  54. result := result + CHARS[Random(Length(CHARS) + 1)];
  55.  
  56. if k <> KeysCount
  57. then result := result + Separator;
  58. end;
  59.  

Por el código puede verse que utiliza todo el abecedario, excepto por la Ñ. Si se va a contemplar la Ñ y viendo que estás empleando Lazarus debes tener en cuenta el tema del encode. Por defecto Lazarus trabaja con UTF8, pero si modificas el código para agregarle la Ñ recibirás en lugar de la Ñ un signo de pregunta ?. Recomiendo leer sobre encoding en Lazarus.

 

Saludos,


  • 0

#7 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 diciembre 2015 - 11:38

Muchas gracias Delphius lo acabo de probar y funciona bien  :)
pero porque ha veces me pone el simbolo de dollar $ en los resultados:

4H$1M-700FL-SRBLG-F$F2Q-H5L77
VFT$4-B0YQP-YSV6Z-9QHPX-6IE$H
452OU#EOAB9#YMPOZ#A5M9$


  • 0

#8 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 11:46

Vaya, no había caído en cuenta que es Lazarus, no Delphi, pues que bueno que las funciones son identicas en ambos productos.

 

Saludos


  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 11:47

Muchas gracias Delphius lo acabo de probar y funciona bien  :)
pero porque ha veces me pone el simbolo de dollar $ en los resultados:

4H$1M-700FL-SRBLG-F$F2Q-H5L77
VFT$4-B0YQP-YSV6Z-9QHPX-6IE$H
452OU#EOAB9#YMPOZ#A5M9$

 

¿Lo modificaste para que trabaje con la Ñ o cualquier otro carácter no ANSI? Porque como he dicho, el código que puse no es "UTF8-friendly" para que trabaja con esos "carácteres extraños" hay que hacer más trabajo. Por eso he dicho que debe estudiarse el tema del encoding.

 

Saludos,


  • 0

#10 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 12:38

Me estoy dando cuenta de que mi código puede mejorarse un poco: directamente en Random() puede ponerse Random(37) de modo que en CHARS[] al sumarse 1 se lea en forma aleatoria desde CHARS[1]  a CHARS[37].

 

Ahora bien, me he quedado pensando en lo la Ñ y del encoding, y quizá no tenga sentido tener que estar aplicando tanto cambios. Debería ser lo mismo asi que probé añadiendo la Ñ.

Hice esto:


delphi
  1. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  2. Separator: char): string;
  3. const
  4. CHARS = 'ABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789';
  5. var k, l: integer;
  6. rnd: string;
  7. begin
  8. {
  9.   rnd := '';
  10.   for k := 1 to KeysCount do
  11.   begin
  12.   for l := 1 to KeysLength do
  13.   rnd := rnd + CHARS[Random(38) + 1];
  14.  
  15.   if k <> KeysCount
  16.   then rnd := rnd + Separator;
  17.   end;
  18.   result := rnd;
  19.   }
  20. ShowMessage(CHARS);
  21.  
  22. for k := 1 to 38 do
  23. rnd := rnd + CHARS[k];
  24.  
  25. ShowMessage(rnd);
  26.  
  27. result := rnd;
  28. end;

Y efectivamente tanto el primer showMessage() como el 2do, y el texto que finalmente se muestra en el Edit son lo mismo y puede leerse Ñ.

Ahora bien esto:


delphi
  1. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  2. Separator: char): string;
  3. const
  4. CHARS = 'ABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789';
  5. var k, l: integer;
  6. rnd: string;
  7. begin
  8. rnd := '';
  9. for k := 1 to KeysCount do
  10. begin
  11. for l := 1 to KeysLength do
  12. rnd := rnd + CHARS[Random(38) + 1];
  13.  
  14. if k <> KeysCount
  15. then rnd := rnd + Separator;
  16. end;
  17. result := rnd;
  18. end;

No respeta la lógica, y se puede obtener cosas como estas: SUZ4U-4S4OV-W?OL5-C8K?Q-22SQT

 

Puede verse que se ha reemplazado la Ñ por el signo de pregunta. Cabe la pregunta entonces, ¿porqué en la muestra anterior respeta la Ñ cuando se lee CHARS[15] y se la concatena para formar la cadena CHARS original y aquí, aún concatenando, no?

 

¡Cosas mandinga!

 

Saludos,


  • 0

#11 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 12:49

Me estoy dando cuenta de que mi código puede mejorarse un poco: directamente en Random() puede ponerse Random(37) de modo que en CHARS[] al sumarse 1 se lea en forma aleatoria desde CHARS[1]  a CHARS[37].

 

Ahora bien, me he quedado pensando en lo la Ñ y del encoding, y quizá no tenga sentido tener que estar aplicando tanto cambios. Debería ser lo mismo asi que probé añadiendo la Ñ.

Hice esto:


delphi
  1. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  2. Separator: char): string;
  3. const
  4. CHARS = 'ABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789';
  5. var k, l: integer;
  6. rnd: string;
  7. begin
  8. {
  9.   rnd := '';
  10.   for k := 1 to KeysCount do
  11.   begin
  12.   for l := 1 to KeysLength do
  13.   rnd := rnd + CHARS[Random(38) + 1];
  14.  
  15.   if k <> KeysCount
  16.   then rnd := rnd + Separator;
  17.   end;
  18.   result := rnd;
  19.   }
  20. ShowMessage(CHARS);
  21.  
  22. for k := 1 to 38 do
  23. rnd := rnd + CHARS[k];
  24.  
  25. ShowMessage(rnd);
  26.  
  27. result := rnd;
  28. end;

Y efectivamente tanto el primer showMessage() como el 2do, y el texto que finalmente se muestra en el Edit son lo mismo y puede leerse Ñ.

Ahora bien esto:


delphi
  1. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  2. Separator: char): string;
  3. const
  4. CHARS = 'ABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789';
  5. var k, l: integer;
  6. rnd: string;
  7. begin
  8. rnd := '';
  9. for k := 1 to KeysCount do
  10. begin
  11. for l := 1 to KeysLength do
  12. rnd := rnd + CHARS[Random(38) + 1];
  13.  
  14. if k <> KeysCount
  15. then rnd := rnd + Separator;
  16. end;
  17. result := rnd;
  18. end;

No respeta la lógica, y se puede obtener cosas como estas: SUZ4U-4S4OV-W?OL5-C8K?Q-22SQT

 

Puede verse que se ha reemplazado la Ñ por el signo de pregunta. Cabe la pregunta entonces, ¿porqué en la muestra anterior respeta la Ñ cuando se lee CHARS[15] y se la concatena para formar la cadena CHARS original y aquí, aún concatenando, no?

 

¡Cosas mandinga!

 

Saludos,

 

Bueno,

 

La longitud de CHARS es 37, si se está buscando el caracter 38 o 39 según el caso no lo va a encontrar y por eso se muestra el signo "?",

 

Lo que yo propongo es utilizar la función pero con Random(36) + 1  o Random(37) según el caso. :)

 

Saludos

 

PD, curioso que nunca haya elegido el 38 en el primer ejemplo :p


  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 01:12

Ups... ando dormido y cuento mal.

 

Pero he probado esto:


php
  1. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  2. Separator: char): string;
  3. const
  4. CHARS = 'ABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789';
  5. var k, l: integer;
  6. rnd: string;
  7. begin
  8. rnd := '';
  9. for k := 1 to KeysCount do
  10. begin
  11. for l := 1 to KeysLength do
  12. rnd := rnd + CHARS[Random(37) + 1];
  13.  
  14. if k <> KeysCount
  15. then rnd := rnd + Separator;
  16. end;
  17. result := rnd;
  18. ShowMessage('Longitud: ' + IntToStr(Length(CHARS)) + ' CHAR[15] = ' + CHARS[15] + ' CHARS[16] = ' + CHARS[16]);

Y obtengo: STY3U-3S3?V-V?OL4-C7K?P-12RPT; y el ShowMessage me dice: "Longitud: 38 CHAR[15] = ? CHARS[16] = "

 

Ya he visto cual es el asunto. Creo saber como tratarlo.

 

Saludos,


  • 0

#13 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 01:25

Y obtengo: STY3U-3S3?V-V?OL4-C7K?P-12RPT; y el ShowMessage me dice: "Longitud: 38 CHAR[15] = ? CHARS[16] = "

 

Ya he visto cual es el asunto. Creo saber como tratarlo.

 

Saludos,

 

Vaya, pues no se de donde sale el 38, si son 27 letras del alfabeto y 10 numeros :s

 

Saludos


  • 0

#14 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 01:26

Función ya corregida:


delphi
  1. function TForm1.RandomStringsKeys(KeysCount, KeysLength: integer;
  2. Separator: char): string;
  3. const
  4. CHARS = 'ABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789';
  5. var k, l, c: integer;
  6. rnd: string;
  7. begin
  8. rnd := '';
  9. for k := 1 to KeysCount do
  10. begin
  11. for l := 1 to KeysLength do
  12. begin
  13. c := Random(37) + 1;
  14. case c of
  15. 15: rnd := rnd + CHARS[c] + CHARS[c+1];
  16. 1..14: rnd := rnd + CHARS[c];
  17. else rnd := rnd + CHARS[c+1];
  18. end;
  19. end;
  20.  
  21. if k <> KeysCount
  22. then rnd := rnd + Separator;
  23. end;
  24. result := rnd;
  25. end;

¡Me están haciendo gastar neuronas che! Ya no me van a quedar siquiera para poder recordar mi nombre :D

 

Saludos,


  • 0

#15 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 01:31

Vaya, pues no se de donde sale el 38, si son 27 letras del alfabeto y 10 numeros :s

 

Saludos

 

Todo se debe a como es que funciona UTF8 amigo. En UTF8 los carácteres son compuestos de dos partes. Para poder almacenar la Ñ se requiere "combinar" el bytecode correspondiente a la ? y al del carácter ´. Es decir Ñ = bytecode(?) + bytecode(´). Para las otras letras no hay drama ya que hay correspondencia directa del esquema ANSI a UTF8. Ñ es tratada de forma "especial".

De este modo Ñ se compone de dos posiciones, de ahí que tenga 38.


  • 0

#16 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 01:35

Todo se debe a como es que funciona UTF8 amigo. En UTF8 los carácteres son compuestos de dos partes. Para poder almacenar la Ñ se requiere "combinar" el bytecode correspondiente a la ? y al del carácter ´. Es decir Ñ = ?´

De este modo Ñ se compone de dos posiciones, de ahí que tenga 38.

 

 

Pero eso en Lazarus ¿no? porque Delphi me da 37.......

 

Saludos


  • 0

#17 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 01:45

Pero eso en Lazarus ¿no? porque Delphi me da 37.......

 

Saludos

 

Efectivamente. Esto es en Lazarus, y el hilo está en el foro de Lazarus. ;) Asi es como funciona en Lazarus, que a menos que se indique lo contrario asume como UTF8. Asi es que cuando uno le pone A en un string, sabe leer la parte alta y baja del bytecode correspondiente. Y cuando lo pones la Ñ, como en mi caso a la variable CHARS, internamente debe trabajar con el esquema ?´ que he descrito antes.

 

Desde que ya no toco Delphi las cosas son diferentes.

 

Se que en un futuro, no muy cercano tengo entendido, Lazarus va ir hacia UTF-16 como lo es Delphi ahora. Desconozco en como se las arregló Delphi internamente para meterse en el UNICODE y poder operar con UTF-16 sin tener que hacer "magia" como yo en Lazarus.

 

Saludos,


  • 0

#18 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 18 diciembre 2015 - 01:48

Efectivamente. Esto es en Lazarus, y el hilo está en el foro de Lazarus. ;) Asi es como funciona en Lazarus, que a menos que se indique lo contrario asume como UTF8. Asi es que cuando uno le pone A en un string, sabe leer la parte alta y baja del bytecode correspondiente. Y cuando lo pones la Ñ, como en mi caso a la variable CHARS, internamente debe trabajar con el esquema ?´ que he descrito antes.

 

 

Si si,  ya lo había dicho en un hilo anterior, solo que me pareció bastante extraño ese comportamiento. 

 

Vaya, no había caído en cuenta que es Lazarus, no Delphi, pues que bueno que las funciones son identicas en ambos productos.

 

Saludos

 

Saludos


  • 0

#19 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 01:57

Pues asi es amigo. Lazarus se esfuerza mucho en tener buena compatibilidad con Delphi y hace que código escrito en Delphi pueda ser portado con casi ningún cambio o sin problemas. Pero como acabas de ver por mis ejemplos también tiene sus grandes diferencias. Quizá si activara la directiva de compilación {mode delphi} en lugar de la que está por defecto {mode objfpc} el código que puse inicialmente (corrigiendo el tema del índice por supuesto) funcione sin problemas.

 

Saludos,


  • 0

#20 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 diciembre 2015 - 02:01

Muchas gracias Delphius por el apoyo, me funciona el último código que compartió :)

Mas si no fuera mucha molestía dos pequeñas consultas:

 

1. Como puedo hacer para trabajar sin las Ñ, pues con tal solo quitarla de la lista el soft genera códigos cortos y largos como esto:

VW16X-6V6QY-YOPRL7-C

OP95CM-DYAN5-

 

2. En la primera ejecución el resultado siempre es:

TUZ4V-4T4OW-WÑPL5-C8KÑQ-23SQU

Ñ73CM-DWAN3-81F55-9Q22Q-S1YEZ

 

Agradezco su ayuda...


  • 0




IP.Board spam blocked by CleanTalk.