/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C/C++.
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
long modulo( long a, long b)
{
return a % b;
}
long euclides( long a, long b)
{
while ( b != 0 )
{
long aux = b;
b = a % b;
a = aux;
}
return a;
}
void eratostenes( long p)
{
int * numeros
= ( int * ) malloc ( p
* sizeof ( int ) ) ; if ( numeros == NULL) {
printf ( "Error en la asignación de memoria.\n " ) ; }
for ( int i = 2 ; i < p; i++ )
{
numeros[ i] = 1 ;
}
for ( int i = 2 ; i * i < p; i++ )
{
if ( numeros[ i] == 1 )
{
for ( int j = i * i; j < p; j += i)
{
numeros[ j] = 0 ;
}
}
}
for ( int i = 2 ; i < p; i++ )
{
if ( numeros[ i] == 1 )
{
}
}
}
void factorizacion( long p)
{
printf ( "Factores primos de %ld: " , p
) ; for ( long i
= 2 ; i
<= sqrt ( p
) ; i
++ ) {
while ( p % i == 0 )
{
p /= i;
}
}
if ( p > 1 )
{
}
}
long entero_menor( long p)
{
}
int es_primo( long n)
{
if ( n < 2 ) return 0 ;
for ( long i
= 2 ; i
<= sqrt ( n
) ; i
++ ) {
if ( n % i == 0 ) return 0 ;
}
return 1 ;
}
long primo_menor( long p)
{
if ( p <= 1 )
{
printf ( "El número debe ser mayor que 1.\n " ) ; }
long n;
do
{
n = entero_menor( p) ;
} while ( ! es_primo( n) ) ;
return n;
}
void inversa( long a, long b)
{
long r0 = b, r1 = a, x0 = 1 ;
long q1 = r0 / r1;
long r2 = modulo( r0, r1) ;
long x1 = - q1;
long x2;
while ( r2!= 0 )
{
r0 = r1;
r1 = r2;
q1 = r0 / r1;
r2 = modulo( r0, r1) ;
x2 = x0 - ( q1* x1) ;
x0 = x1;
x1 = x2;
}
if ( r1!= 1 )
{
printf ( "No existe la inversa.\n " ) ; }
if ( x0> 0 )
{
printf ( "La inversa es %ld.\n " , x0
) ;
}
else
{
printf ( "La inversa es %ld.\n " , x0
+ b
) ; }
}
long exponenciacion( long a, long x, long n)
{
long y = 1 ;
long u = a % n;
while ( x!= 0 )
{
if ( ( x% 2 ) == 1 ) y = ( y* u) % n;
x = x/ 2 ;
u = ( u* u) % n;
}
return y;
}
long es_generador( long g, long p)
{
long p1 = p - 1 ;
for ( long q = 2 ; q * q <= p1; q++ )
{
if ( p1 % q == 0 )
{
// Si g^((p-1)/q) ≡ 1 mod p → no es generador
if ( exponenciacion( g, p1 / q, p) == 1 )
return 0 ;
// Eliminar potencias de q para evitar redundancia
while ( p1 % q == 0 )
p1 /= q;
}
}
// Verificar el último factor si quedó uno mayor que sqrt(p1)
if ( p1 > 1 )
{
if ( exponenciacion( g, ( p - 1 ) / p1, p) == 1 )
return 0 ;
}
return 1 ;
}
void generadores( long p)
{
if ( ! es_primo( p) )
{
printf ( "El número %ld no es primo.\n " , p
) ; return ;
}
for ( long g = 2 ; g < p; g++ )
{
if ( es_generador( g, p) )
{
printf ( "%ld es un generador de Z%ld\n " , g
, p
) ; }
}
}
void legendre( long a, long p)
{
if ( euclides( a, p) != 1 )
{
printf ( "El símbolo de Legendre no está definido para estos valores.\n " ) ; return ;
}
long resultado = exponenciacion( a, ( p - 1 ) / 2 , p) ;
if ( resultado == p - 1 )
{
printf ( "El símbolo de Legendre (%ld/%ld) es -1.\n " , a
, p
) ; }
else
{
printf ( "El símbolo de Legendre (%ld/%ld) es 1.\n " , a
, p
) ; }
}
int jacobi( long a, long n)
{
if ( n <= 1 || n % 2 == 0 )
{
printf ( "El valor de n debe ser un número impar mayor que 1.\n " ) ; return 0 ;
}
int j = 1 ;
while ( a != 0 )
{
while ( a % 2 == 0 )
{
a /= 2 ;
if ( n % 8 == 3 || n % 8 == 5 )
{
j = - j;
}
}
long temp = a;
a = n % a;
n = temp;
if ( a % 4 == 3 && n % 4 == 3 )
{
j = - j;
}
}
if ( n == 1 )
{
return j;
}
return 0 ;
}
int main( )
{
char letra;
long resultado, a, b, c;
printf ( " b) MCD de a y b usando el algoritmo de Euclides\n " ) ; printf ( " c) Criba de Eratóstenes dado un número máximo p\n " ) ; printf ( " d) Factorización de un número p por fuerza bruta\n " ) ; printf ( " e) Generar un número entero aleatorio x menor que p\n " ) ; printf ( " f) Generar, por fuerza bruta, un número primo x menor que p\n " ) ; printf ( " g) Calcular, si existe, la inversa x = a-1 mod b\n " ) ; printf ( " h) Calcular la exponenciación Y = a^x mod n\n " ) ; printf ( " i) Calcular por fuerza bruta todos los generadores del grupo Zp con p primo\n " ) ; printf ( " j) Verificar analiticamente si un número x es generador del grupo Zp\n " ) ; printf ( " k) Calcular el símbolo de Legendre(a/p)\n " ) ; printf ( " l) Calcular el símbolo de Jacobi(a/n)\n " ) ; switch ( letra)
{
case 'a' :
printf ( "Introduce el primer número:\n " ) ; printf ( "Introduce el segundo número:\n " ) ; resultado = modulo( a, b) ;
break ;
case 'b' :
printf ( "Introduce el primer número:\n " ) ; printf ( "Introduce el segundo número:\n " ) ; resultado = euclides( a, b) ;
break ;
case 'c' :
printf ( "Introduce un número:\n " ) ; eratostenes( a) ;
break ;
case 'd' :
printf ( "Introduce un número:\n " ) ; factorizacion( a) ;
break ;
case 'e' :
printf ( "Introduce un número:\n " ) ; resultado = entero_menor( a) ;
break ;
case 'f' :
printf ( "Introduce un número:\n " ) ; resultado = primo_menor( a) ;
break ;
case 'g' :
printf ( "Introduce el primer número:\n " ) ; printf ( "Introduce el segundo número:\n " ) ; inversa( a, b) ;
break ;
case 'h' :
printf ( "Introduce el número a:\n " ) ; printf ( "Introduce el número x:\n " ) ; printf ( "Introduce el número n:\n " ) ; resultado = exponenciacion( a, b, c) ;
break ;
case 'i' :
printf ( "Introduce un número:\n " ) ; generadores( a) ;
break ;
case 'j' :
printf ( "Introduce un número x:\n " ) ; printf ( "Introduce un número p:\n " ) ; if ( es_generador( a, b) )
{
printf ( "%ld es un generador de Z%ld\n " , a
, b
) ; }
else
{
printf ( "%ld no es un generador de Z%ld\n " , a
, b
) ; }
break ;
case 'k' :
printf ( "Introduce el primer número:\n " ) ; printf ( "Introduce el segundo número:\n " ) ; legendre( a, b) ;
break ;
case 'l' :
printf ( "Introduce el primer número:\n " ) ; printf ( "Introduce el segundo número:\n " ) ; resultado = jacobi( a, b) ;
if ( resultado != 0 )
{
printf ( "El símbolo de Jacobi (%ld/%ld) es %ld.\n " , a
, b
, resultado
) ; }
else
{
printf ( "Error en el cálculo del símbolo de Jacobi.\n " ) ; }
break ;
case 'z' :
return 0 ;
default :
printf ( "Opción no válida.\n " ) ; break ;
}
return 0 ;
}
LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoKV2VsY29tZSB0byBHREIgT25saW5lLgpHREIgb25saW5lIGlzIGFuIG9ubGluZSBjb21waWxlciBhbmQgZGVidWdnZXIgdG9vbCBmb3IgQy9DKysuCkNvZGUsIENvbXBpbGUsIFJ1biBhbmQgRGVidWcgb25saW5lIGZyb20gYW55d2hlcmUgaW4gd29ybGQuCgoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8bWF0aC5oPgojaW5jbHVkZSA8dGltZS5oPgoKbG9uZyBtb2R1bG8obG9uZyBhLCBsb25nIGIpCnsKICByZXR1cm4gYSAlIGI7Cn0KCmxvbmcgZXVjbGlkZXMobG9uZyBhLCBsb25nIGIpCnsKICAgIHdoaWxlIChiICE9IDApCiAgICB7CiAgICAgICAgbG9uZyBhdXggPSBiOwogICAgICAgIGIgPSBhICUgYjsKICAgICAgICBhID0gYXV4OwogICAgfQogICAgcmV0dXJuIGE7Cn0KCnZvaWQgZXJhdG9zdGVuZXMobG9uZyBwKQp7CiAgICBpbnQgKm51bWVyb3MgPSAoaW50KikgbWFsbG9jKHAgKiBzaXplb2YoaW50KSk7CiAgICBpZiAobnVtZXJvcyA9PSBOVUxMKSB7CiAgICAgICAgcHJpbnRmKCJFcnJvciBlbiBsYSBhc2lnbmFjacOzbiBkZSBtZW1vcmlhLlxuIik7CiAgICAgICAgZXhpdCgxKTsKICAgIH0KICAgIGZvciAoaW50IGkgPSAyOyBpIDwgcDsgaSsrKQogICAgewogICAgICAgIG51bWVyb3NbaV0gPSAxOwogICAgfQoKICAgIGZvciAoaW50IGkgPSAyOyBpICogaSA8IHA7IGkrKykKICAgIHsKICAgICAgICBpZiAobnVtZXJvc1tpXSA9PSAxKQogICAgICAgIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IGkgKiBpOyBqIDwgcDsgaiArPSBpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBudW1lcm9zW2pdID0gMDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBmb3IgKGludCBpID0gMjsgaSA8IHA7IGkrKykKICAgIHsKICAgICAgICBpZiAobnVtZXJvc1tpXSA9PSAxKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbnRmKCIlZCAiLCBpKTsKICAgICAgICB9CiAgICB9CglmcmVlKG51bWVyb3MpOwp9Cgp2b2lkIGZhY3Rvcml6YWNpb24obG9uZyBwKQp7CiAgICBwcmludGYoIkZhY3RvcmVzIHByaW1vcyBkZSAlbGQ6ICIsIHApOwogICAgZm9yIChsb25nIGkgPSAyOyBpIDw9IHNxcnQocCk7IGkrKykKICAgIHsKICAgICAgICB3aGlsZSAocCAlIGkgPT0gMCkKICAgICAgICB7CiAgICAgICAgICAgIHByaW50ZigiJWxkICIsIGkpOwogICAgICAgICAgICBwIC89IGk7CiAgICAgICAgfQogICAgfQoJaWYgKHAgPiAxKQogICAgewogICAgICAgIHByaW50ZigiJWxkIiwgcCk7CiAgICB9CiAgICBwcmludGYoIlxuIik7Cn0KCmxvbmcgZW50ZXJvX21lbm9yKGxvbmcgcCkKewogICAgcmV0dXJuIHJhbmQoKSAlIHA7Cn0KCmludCBlc19wcmltbyhsb25nIG4pCnsKICAgIGlmIChuIDwgMikgcmV0dXJuIDA7CiAgICBmb3IgKGxvbmcgaSA9IDI7IGkgPD0gc3FydChuKTsgaSsrKQogICAgewogICAgICAgIGlmIChuICUgaSA9PSAwKSByZXR1cm4gMDsKICAgIH0KICAgIHJldHVybiAxOwp9Cgpsb25nIHByaW1vX21lbm9yKGxvbmcgcCkKewoJaWYgKHAgPD0gMSkKCXsKCQlwcmludGYoIkVsIG7Dum1lcm8gZGViZSBzZXIgbWF5b3IgcXVlIDEuXG4iKTsKCQlleGl0KDEpOwoJfQogICAgbG9uZyBuOwogICAgZG8KICAgIHsKICAgICAgICBuID0gZW50ZXJvX21lbm9yKHApOwogICAgfSB3aGlsZSAoIWVzX3ByaW1vKG4pKTsKCiAgICByZXR1cm4gbjsKfQoKdm9pZCBpbnZlcnNhKGxvbmcgYSwgbG9uZyBiKQp7Cglsb25nIHIwID0gYiwgcjEgPSBhLCB4MCA9IDE7Cglsb25nIHExID0gcjAgLyByMTsKCWxvbmcgcjIgPSBtb2R1bG8ocjAscjEpOwoJbG9uZyB4MSA9IC1xMTsKCWxvbmcgeDI7Cgl3aGlsZSAocjIhPTApCgl7CgkJcjAgPSByMTsKCQlyMSA9IHIyOwoJCXExID0gcjAgLyByMTsKCQlyMiA9IG1vZHVsbyhyMCxyMSk7CgkJeDIgPSB4MCAtIChxMSp4MSk7CgkJeDAgPSB4MTsKCQl4MSA9IHgyOwoJfQoJaWYgKHIxIT0xKQoJewoJCXByaW50ZigiTm8gZXhpc3RlIGxhIGludmVyc2EuXG4iKTsKCQlleGl0KDApOwoJfQoJaWYgKHgwPjApCgl7CgkJcHJpbnRmKCJMYSBpbnZlcnNhIGVzICVsZC5cbiIsIHgwKTsKCQkKCX0KCWVsc2UKCXsKCQlwcmludGYoIkxhIGludmVyc2EgZXMgJWxkLlxuIiwgeDAgKyBiKTsKCX0KfQoKbG9uZyBleHBvbmVuY2lhY2lvbihsb25nIGEsIGxvbmcgeCwgbG9uZyBuKQp7Cglsb25nIHkgPSAxOwoJbG9uZyB1ID0gYSAlIG47Cgl3aGlsZSh4IT0wKQoJewoJCWlmKCh4JTIpPT0xKSB5ID0gKHkqdSkgJSBuOwoJCXggPSB4LzI7CgkJdSA9ICh1KnUpICUgbjsKCX0KCXJldHVybiB5Owp9Cgpsb25nIGVzX2dlbmVyYWRvcihsb25nIGcsIGxvbmcgcCkKewogICAgbG9uZyBwMSA9IHAgLSAxOwogICAgZm9yIChsb25nIHEgPSAyOyBxICogcSA8PSBwMTsgcSsrKQogICAgewogICAgICAgIGlmIChwMSAlIHEgPT0gMCkKICAgICAgICB7CiAgICAgICAgICAgIC8vIFNpIGdeKChwLTEpL3EpIOKJoSAxIG1vZCBwIOKGkiBubyBlcyBnZW5lcmFkb3IKICAgICAgICAgICAgaWYgKGV4cG9uZW5jaWFjaW9uKGcsIHAxIC8gcSwgcCkgPT0gMSkKICAgICAgICAgICAgICAgIHJldHVybiAwOwoKICAgICAgICAgICAgLy8gRWxpbWluYXIgcG90ZW5jaWFzIGRlIHEgcGFyYSBldml0YXIgcmVkdW5kYW5jaWEKICAgICAgICAgICAgd2hpbGUgKHAxICUgcSA9PSAwKQogICAgICAgICAgICAgICAgcDEgLz0gcTsKICAgICAgICB9CiAgICB9CgogICAgLy8gVmVyaWZpY2FyIGVsIMO6bHRpbW8gZmFjdG9yIHNpIHF1ZWTDsyB1bm8gbWF5b3IgcXVlIHNxcnQocDEpCiAgICBpZiAocDEgPiAxKQogICAgewogICAgICAgIGlmIChleHBvbmVuY2lhY2lvbihnLCAocCAtIDEpIC8gcDEsIHApID09IDEpCiAgICAgICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIHJldHVybiAxOwp9Cgp2b2lkIGdlbmVyYWRvcmVzKGxvbmcgcCkKewogICAgaWYgKCFlc19wcmltbyhwKSkKICAgIHsKICAgICAgICBwcmludGYoIkVsIG7Dum1lcm8gJWxkIG5vIGVzIHByaW1vLlxuIiwgcCk7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGZvciAobG9uZyBnID0gMjsgZyA8IHA7IGcrKykKICAgIHsKICAgICAgICBpZiAoZXNfZ2VuZXJhZG9yKGcsIHApKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbnRmKCIlbGQgZXMgdW4gZ2VuZXJhZG9yIGRlIFolbGRcbiIsIGcsIHApOwogICAgICAgIH0KICAgIH0KfQoKdm9pZCBsZWdlbmRyZShsb25nIGEsIGxvbmcgcCkKewogICAgaWYgKGV1Y2xpZGVzKGEsIHApICE9IDEpCgl7CiAgICAgICAgcHJpbnRmKCJFbCBzw61tYm9sbyBkZSBMZWdlbmRyZSBubyBlc3TDoSBkZWZpbmlkbyBwYXJhIGVzdG9zIHZhbG9yZXMuXG4iKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBsb25nIHJlc3VsdGFkbyA9IGV4cG9uZW5jaWFjaW9uKGEsIChwIC0gMSkgLyAyLCBwKTsKICAgIGlmIChyZXN1bHRhZG8gPT0gcCAtIDEpCgl7CiAgICAgICAgcHJpbnRmKCJFbCBzw61tYm9sbyBkZSBMZWdlbmRyZSAoJWxkLyVsZCkgZXMgLTEuXG4iLCBhLCBwKTsKICAgIH0KCWVsc2UKCXsKICAgICAgICBwcmludGYoIkVsIHPDrW1ib2xvIGRlIExlZ2VuZHJlICglbGQvJWxkKSBlcyAxLlxuIiwgYSwgcCk7CiAgICB9Cn0KCmludCBqYWNvYmkobG9uZyBhLCBsb25nIG4pCnsKICAgIGlmIChuIDw9IDEgfHwgbiAlIDIgPT0gMCkKCXsKICAgICAgICBwcmludGYoIkVsIHZhbG9yIGRlIG4gZGViZSBzZXIgdW4gbsO6bWVybyBpbXBhciBtYXlvciBxdWUgMS5cbiIpOwogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIGludCBqID0gMTsKICAgIHdoaWxlIChhICE9IDApCgl7CiAgICAgICAgd2hpbGUgKGEgJSAyID09IDApCgkJewogICAgICAgICAgICBhIC89IDI7CiAgICAgICAgICAgIGlmIChuICUgOCA9PSAzIHx8IG4gJSA4ID09IDUpCgkJCXsKICAgICAgICAgICAgICAgIGogPSAtajsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsb25nIHRlbXAgPSBhOwogICAgICAgIGEgPSBuICUgYTsKICAgICAgICBuID0gdGVtcDsKICAgICAgICBpZiAoYSAlIDQgPT0gMyAmJiBuICUgNCA9PSAzKQoJCXsKICAgICAgICAgICAgaiA9IC1qOwogICAgICAgIH0KICAgIH0KICAgIGlmIChuID09IDEpCgl7CiAgICAgICAgcmV0dXJuIGo7CiAgICB9CiAgICByZXR1cm4gMDsKfQoKaW50IG1haW4oKQp7CglzcmFuZCh0aW1lKE5VTEwpKTsKCWNoYXIgbGV0cmE7Cglsb25nIHJlc3VsdGFkbywgYSwgYiwgYzsKCXByaW50ZigiUHVsc2UgdW5hIGxldHJhOlxuIik7CglwcmludGYoIglhKSBhIG1vZCBiXG4iKTsKCXByaW50ZigiCWIpIE1DRCBkZSBhIHkgYiB1c2FuZG8gZWwgYWxnb3JpdG1vIGRlIEV1Y2xpZGVzXG4iKTsKCXByaW50ZigiCWMpIENyaWJhIGRlIEVyYXTDs3N0ZW5lcyBkYWRvIHVuIG7Dum1lcm8gbcOheGltbyBwXG4iKTsKCXByaW50ZigiCWQpIEZhY3Rvcml6YWNpw7NuIGRlIHVuIG7Dum1lcm8gcCBwb3IgZnVlcnphIGJydXRhXG4iKTsKCXByaW50ZigiCWUpIEdlbmVyYXIgdW4gbsO6bWVybyBlbnRlcm8gYWxlYXRvcmlvIHggbWVub3IgcXVlIHBcbiIpOwoJcHJpbnRmKCIJZikgR2VuZXJhciwgcG9yIGZ1ZXJ6YSBicnV0YSwgdW4gbsO6bWVybyBwcmltbyB4IG1lbm9yIHF1ZSBwXG4iKTsKCXByaW50ZigiCWcpIENhbGN1bGFyLCBzaSBleGlzdGUsIGxhIGludmVyc2EgeCA9IGEtMSBtb2QgYlxuIik7CglwcmludGYoIgloKSBDYWxjdWxhciBsYSBleHBvbmVuY2lhY2nDs24gWSA9IGFeeCBtb2QgblxuIik7CglwcmludGYoIglpKSBDYWxjdWxhciBwb3IgZnVlcnphIGJydXRhIHRvZG9zIGxvcyBnZW5lcmFkb3JlcyBkZWwgZ3J1cG8gWnAgY29uIHAgcHJpbW9cbiIpOwoJcHJpbnRmKCIJaikgVmVyaWZpY2FyIGFuYWxpdGljYW1lbnRlIHNpIHVuIG7Dum1lcm8geCBlcyBnZW5lcmFkb3IgZGVsIGdydXBvIFpwXG4iKTsKCXByaW50ZigiCWspIENhbGN1bGFyIGVsIHPDrW1ib2xvIGRlIExlZ2VuZHJlKGEvcClcbiIpOwoJcHJpbnRmKCIJbCkgQ2FsY3VsYXIgZWwgc8OtbWJvbG8gZGUgSmFjb2JpKGEvbilcbiIpOwoJcHJpbnRmKCIJeikgU2FsaXJcbiIpOwoJc2NhbmYoIiVjIiwmbGV0cmEpOwoJc3dpdGNoIChsZXRyYSkKCXsKCQljYXNlICdhJzoKCQkJcHJpbnRmKCJJbnRyb2R1Y2UgZWwgcHJpbWVyIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlwcmludGYoIkludHJvZHVjZSBlbCBzZWd1bmRvIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmIpOwoJCQlyZXN1bHRhZG8gPSBtb2R1bG8oYSwgYik7CgkJCXByaW50ZigiJWxkXG4iLCByZXN1bHRhZG8pOwoJCQlicmVhazsKCQkJCgkJY2FzZSAnYic6CgkJCXByaW50ZigiSW50cm9kdWNlIGVsIHByaW1lciBuw7ptZXJvOlxuIik7CgkJCXNjYW5mKCIlbGQiLCZhKTsKCQkJcHJpbnRmKCJJbnRyb2R1Y2UgZWwgc2VndW5kbyBuw7ptZXJvOlxuIik7CgkJCXNjYW5mKCIlbGQiLCZiKTsKCQkJcmVzdWx0YWRvID0gZXVjbGlkZXMoYSwgYik7CgkJCXByaW50ZigiJWxkXG4iLCByZXN1bHRhZG8pOwoJCQlicmVhazsKCQkJCgkJY2FzZSAnYyc6CgkJCXByaW50ZigiSW50cm9kdWNlIHVuIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQllcmF0b3N0ZW5lcyhhKTsKCQkJYnJlYWs7CgkJCQoJCWNhc2UgJ2QnOgoJCQlwcmludGYoIkludHJvZHVjZSB1biBuw7ptZXJvOlxuIik7CgkJCXNjYW5mKCIlbGQiLCZhKTsKCQkJZmFjdG9yaXphY2lvbihhKTsKCQkJYnJlYWs7CgkJCgkJY2FzZSAnZSc6CgkJCXByaW50ZigiSW50cm9kdWNlIHVuIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlyZXN1bHRhZG8gPSBlbnRlcm9fbWVub3IoYSk7CgkJCXByaW50ZigiJWxkXG4iLCByZXN1bHRhZG8pOwoJCQlicmVhazsKCQkJCgkJY2FzZSAnZic6CgkJCXByaW50ZigiSW50cm9kdWNlIHVuIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlyZXN1bHRhZG8gPSBwcmltb19tZW5vcihhKTsKCQkJcHJpbnRmKCIlbGRcbiIsIHJlc3VsdGFkbyk7CgkJCWJyZWFrOwoJCQoJCWNhc2UgJ2cnOgoJCQlwcmludGYoIkludHJvZHVjZSBlbCBwcmltZXIgbsO6bWVybzpcbiIpOwoJCQlzY2FuZigiJWxkIiwmYSk7CgkJCXByaW50ZigiSW50cm9kdWNlIGVsIHNlZ3VuZG8gbsO6bWVybzpcbiIpOwoJCQlzY2FuZigiJWxkIiwmYik7CgkJCWludmVyc2EoYSwgYik7CgkJCWJyZWFrOwoJCQoJCWNhc2UgJ2gnOgoJCQlwcmludGYoIkludHJvZHVjZSBlbCBuw7ptZXJvIGE6XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlwcmludGYoIkludHJvZHVjZSBlbCBuw7ptZXJvIHg6XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmIpOwoJCQlwcmludGYoIkludHJvZHVjZSBlbCBuw7ptZXJvIG46XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmMpOwoJCQlyZXN1bHRhZG8gPSBleHBvbmVuY2lhY2lvbihhLGIsYyk7CgkJCXByaW50ZigiJWxkXG4iLCByZXN1bHRhZG8pOwoJCQlicmVhazsKCQkJCgkJY2FzZSAnaSc6CgkJCXByaW50ZigiSW50cm9kdWNlIHVuIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlnZW5lcmFkb3JlcyhhKTsKCQkJYnJlYWs7CgkJCQoJCWNhc2UgJ2onOgoJCQlwcmludGYoIkludHJvZHVjZSB1biBuw7ptZXJvIHg6XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlwcmludGYoIkludHJvZHVjZSB1biBuw7ptZXJvIHA6XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmIpOwoJCQlpZihlc19nZW5lcmFkb3IoYSxiKSkKCQkJewoJCQkJcHJpbnRmKCIlbGQgZXMgdW4gZ2VuZXJhZG9yIGRlIFolbGRcbiIsIGEsIGIpOwoJCQl9CgkJCWVsc2UKCQkJewoJCQkJcHJpbnRmKCIlbGQgbm8gZXMgdW4gZ2VuZXJhZG9yIGRlIFolbGRcbiIsIGEsIGIpOwoJCQl9CgkJCWJyZWFrOwoJCQkKCQljYXNlICdrJzoKCQkJcHJpbnRmKCJJbnRyb2R1Y2UgZWwgcHJpbWVyIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmEpOwoJCQlwcmludGYoIkludHJvZHVjZSBlbCBzZWd1bmRvIG7Dum1lcm86XG4iKTsKCQkJc2NhbmYoIiVsZCIsJmIpOwoJCQlsZWdlbmRyZShhLCBiKTsKCQkJYnJlYWs7CgkJCQoJCWNhc2UgJ2wnOgoJCQlwcmludGYoIkludHJvZHVjZSBlbCBwcmltZXIgbsO6bWVybzpcbiIpOwoJCQlzY2FuZigiJWxkIiwmYSk7CgkJCXByaW50ZigiSW50cm9kdWNlIGVsIHNlZ3VuZG8gbsO6bWVybzpcbiIpOwoJCQlzY2FuZigiJWxkIiwmYik7CgkJCXJlc3VsdGFkbyA9IGphY29iaShhLCBiKTsKCQkJaWYgKHJlc3VsdGFkbyAhPSAwKQoJICAgICAgICB7CiAgICAgICAgICAgICAgICBwcmludGYoIkVsIHPDrW1ib2xvIGRlIEphY29iaSAoJWxkLyVsZCkgZXMgJWxkLlxuIiwgYSwgYiwgcmVzdWx0YWRvKTsKICAgICAgICAgICAgfQoJICAgICAgICBlbHNlCgkgICAgICAgIHsKICAgICAgICAgICAgICAgIHByaW50ZigiRXJyb3IgZW4gZWwgY8OhbGN1bG8gZGVsIHPDrW1ib2xvIGRlIEphY29iaS5cbiIpOwogICAgICAgICAgICB9CgkJCWJyZWFrOwoJCQkKCQljYXNlICd6JzoKCQkJcmV0dXJuIDA7CgkJCQoJCWRlZmF1bHQ6CgkJCXByaW50ZigiT3BjacOzbiBubyB2w6FsaWRhLlxuIik7CiAgICAgICAgICAgIGJyZWFrOwoJfQoJcmV0dXJuIDA7Cn0=