jueves, 1 de diciembre de 2011

Rotate array k times in linear time

int gcd ( int a, int b )
{
  int c;
  while ( a != 0 ) {
     c = a; a = b%a;  b = c;
  }
  return b;
}


void shift(volatile int*arr, int len, int k){
    int i,j,c;
    int t1,t2;
    printf("gcd:%d\n",gcd(len,k));
    for(i=0;i<gcd(len,k);i++){
        j=k+i;
        if(j>=len)
            j-=len;
        t1 = arr[j];
        arr[j]=arr[i];
        while(j!=i){
            j+=k;
            if(j>=len)
                j-=len;
            t2 = arr[j];
            arr[j]=t1;
            t1=t2;
            printf("j:%d\n",j);
            for(c=0;c<len;c++)printf("%d,",arr[c]);
            printf("\n");
        }
        printf("i:%d\n",i);
    }
}

sábado, 20 de agosto de 2011

Oscilador 60Hz - 60Hz oscillator

Buscando un oscilador robusto (nada de op amps o compuertas lógicas) para transformar 12 VDC a cuadrada, encontré y modifiqué un circuito para obtener el oscilador:



¿Qué tiene de especial este oscilador? Bueno pues al ser resistencias y transistores lo que se puede calentar, se pueden poner elementos de potencia, y así evitarse problemas de corrientes altas. Siempre se podría poner un muy buen amplificador a osciladores menos potentes, pero no es tan fácil. El funcionamiento del circuito es fácil de entender si se asume que al principio uno de los capacitores está cargado, y el otro no.

60Hz.... efectivamente, este serviría para manejar un puente H con un transformador 12V/127V creando así un inversor.

jueves, 18 de agosto de 2011

Algo sobre la música

Leyendo una discusión en internet sobre la reinvención de la música y el sonido trece, pensé que sería bueno e interesante informarse empíricamente. Lo primero fue encontrar las frecuencias de las notas en la escala más utilizada que usa 12 semitonos http://www.phy.mtu.edu/~suits/notefreqs.html. Después de analizarla vemos que las notas van de acuerdo a una escala logarítmica. Si empezamos con las primeras notas y las vamos multiplicando por 2^x tenemos sus subsecuentes octavas. El código en Matlab sería éste (en este caso partí de la octava número 7 y empecé a dividir, para no perder precisión):
f=[2093.00 2217.46 2349.32 2489.02 2637.02 2793.83 2959.96 3135.96 3322.44 3520.00 3729.31 3951.07]; %frecuencias base
fr=zeros(12,8); %rango de frecuencias
for i =1:8
fr(1:12,9-i)=f/2^(i-1);
end

Así nos ahorramos el trabajo de copiar frecuencia por frecuencia. Ahora, siguiendo con el análisis, en cada octava las 12 notas están distribuidas logarítmicamente entre 2^x y 2^(x+1). Es decir si A2=110 * 2^(0) A#3=110*2^(1/12) B3=110*2^(1/6) C3=110*2^(1/4) ...Es lógico que, por ejemplo, A3 y A4 suenen tan bien. Si vemos la gráfica de ambas señales:



Vemos que tienen una simetría inherente(una cruza dos veces por cero por cada vez que la otra lo hace). ¿Pero entonces porque el acorde mayor? Gráfica del acorde mayor(Seminotas 0-4-7):




MMhhh no encuentro un patrón muy reconocible. Quizás la suma de las 3 se vea mejor:



Se puede distinguir la repetición de un patrón. Ya nada más para comparar, veamos la suma de un disminuído(seminotas 0-3-6-9):



Tengo que decir que se ve mucho más coherente la suma de las notas de un acorde mayor que el de un disminuído! Ahora sí, veamos el análisis en frecuencia:

La primera hipótesis sobre lo que hace que una nota suene bien cuando se toca seguida o en conjunto con otra, es que sus frecuencias (o longitudes de onda) sean múltiplos. Para A2 y A3 es claro que 2*A2=A3, ¿pero qué con la tercera mayor y la quinta?:
(2^(x + 1/3))/2^x = 2^(1/3)= 1.2599
(2^(x + 7/12))/2^x = 2^(7/12)= 1.4983

Podemos ver que la tercer se aproxima a 1.25 y la 5 a 1.5. Eso explicaría el porqué de la armonía. Curiosamente si buscamos la nota que se asemeje más a 1.75 sería la 6ta (A para C p.ej.) 2^(9/12)=1.7818. No es tan cerca como las otras dos aparte de que rompe con la escala logarítmica de (1/2)^n. Quizás es por eso que no se utiliza tanto en acordes... Entonces parece ser que en efecto, frecuencias en la forma de f+(1/2)^n suenan armónicas con la frecuencia base f.

Dos preguntas me saltan a la mente:
1- ¿Por qué dividir el lapso de 2^x a 2^(x+1) en 12?
2- ¿Qué pasa si las escalas las basamos en lapsos con bases primas distintas a 2, por ejemplo 3^x a 3^(x+1) o 5^x a 5^(x+1)?

Creo que para reinventar la música, o crear un nuevo paradigma hay muuucho espacio.... Lo importante de las 12 notas, creo yo, es que la 3 y la 5 se parecen mucho a 1.25 y 1.5. O quizás haya el otro extremo donde la nota es totalmente átona con la frecuencia base, algo así como f+pi/6... y por eso las 12 seminotas son tan especiales: contienen tanto a notas armónicas como a notas no armónicas.

Si fuera yo a inventar mi propia escala creo que pondría la nota base, f*1.25, f*1.5,f*1.75. Aparte de estas pondría quizás f*1.333, f*1.6666. Llevo 6 mhhh... Ya nada más para rematar las últimas 4 serían algo así como f*1.171234321, f*(1+1/e), f*phi y f*(1+pi/e).

Siguiente proyecto: Hacer un instrumento electrónico donde puedas tocar notas como f+(1/primo(n))^k donde n y k son naturales. Aparte de éstas base, puedas añadir notas a mano con decimales o fracciones que tú eligas. ¿Me pregunto cómo sonaría esa música?


miércoles, 25 de mayo de 2011

Qué belleza!




Motores:

Motor DC 5kW 500V 10A

Motor AC trifásico 15kW 500Vrms 20 Arms 50Hz

Acoplados a un sistema con momento rotacional de inercia variable y medidores de rpm.

Aparatos:
Osciloscopio 4 canales a color con conexión LAN-ethernet, FFT hasta 1GHz
Simo inversor de DC a AC 20kW
Regulador de momento rotacional de inercia
Regulador de 3 fases AC a DC
Medidor de potencia reactiva, real y pf.
Analizador de señales de corriente y voltage para alta potencia (<10kW). FFT, valores rms pico pico, distorción harmónica...

Computadora con LabView controlando todo el equipo :D

jueves, 28 de abril de 2011

Project Euler 61

Tengo que decir que me llevo un buen rato resolver éste. Al final mi solución tarda unos cuantos ms... Escribí mi propio método para permutar (lo cual SIEMPRE me había dado mucha flojera), y otros cuantos. Estuvo pesado pero lo saqué:

Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygonal) numbers and are generated by the following formulae:

Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ...
Square P4,n=n2 1, 4, 9, 16, 25, ...
Pentagonal P5,n=n(3n1)/2 1, 5, 12, 22, 35, ...
Hexagonal P6,n=n(2n1) 1, 6, 15, 28, 45, ...
Heptagonal P7,n=n(5n3)/2 1, 7, 18, 34, 55, ...
Octagonal P8,n=n(3n2) 1, 8, 21, 40, 65, ...
The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three interesting properties.

The set is cyclic, in that the last two digits of each number is the first two digits of the next number (including the last number with the first).
Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and pentagonal (P5,44=2882), is represented by a different number in the set.
This is the only set of 4-digit numbers with this property.
Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set.

Approaches:

1.- Fuerza muy a lo bruta. Combinaciones de 2 en 1000 a 9999. Si tienen chance, seguir con tercer número etc. etc. Muy largo....
2.- Sacar la lista de todos los números poligonales, y hacer lo mismo que en el paso anterior: Funciona, aunque todavía se pueda mejorar mucho más, y con menos códgio:

 import java.util.ArrayList;  
 import java.util.Arrays;  
 import java.util.HashMap;  
 /**  
 *  
 * @author Andres  
 */  
 public class pe61{  
 public static void main(String[] args) throws InterruptedException{  
 HashMap tups = new HashMap();  
 double a = 0.5;  
 double b = 0.5;  
 for (int j = 0; j &lt; 6; j++){  
 int i = 0;  
 int k = (int)(a*i*i+b*i);  
 while(k<1000 data-blogger-escaped-br=""> i++;  
 k = (int)(a*i*i+b*i);  
 }  
 while(k<10000 data-blogger-escaped-br=""> tups.put(k,j);  
 i++;  
 k = (int)(a*i*i+b*i);  
 }  
 a+=0.5;  
 b-=0.5;  
 System.out.println("size: " + tups.size());  
 }  
 System.out.println(isSCycle(new int[]{3066,6655}));  
 for (Integer integer : tups.keySet()) {  
 findCycle(new int[]{integer},tups);  
 System.out.println(integer);  
 }  
 }  
 public static void findCycle(int[] in, HashMap list){  
 for (Integer integer : list.keySet()) {  
 boolean ret = false;  
 for(int c = 0 ; c &lt; in.length;c++)  
 if(integer==in[c] || list.get(integer) == list.get(in[c]))  
 ret = true;  
 if(ret)  
 continue;  
 int[] arr = new int[in.length+1];  
 for (int j = 0; j &lt; in.length; j++)  
 arr[j]=in[j];  
 arr[arr.length-1]=integer;  
 if(arr.length==6 &amp;&amp; isCycle(arr)){  
 System.err.println(Arrays.toString(arr));  
 return;  
 } else if(arr.length==6){  
 //System.out.println(Arrays.toString(arr));  
 return;  
 }else if (isSCycle(arr)){  
 findCycle(arr,list);  
 }  
 }  
 }  
 public static long iFact(long x) {  
 for (long i = x - 1; i &gt; 1; i--) {  
 x = x * i;  
 }  
 return x;  
 }  
 public static boolean isSCycle(int[] arr){  
 String[] s = new String[arr.length];  
 for (int i = 0; i &lt; s.length; i++)  
 s[i]=arr[i]+"";  
 String[][] perms = new String[(int)iFact(arr.length)][arr.length];  
 permute(perms,0,s,0);  
 for (int i = 0; i &lt; perms.length; i++) {  
 boolean check = true;  
 for (int j = 0; j &lt; perms[i].length-1; j++) {  
 if(!perms[i][j].substring(2, 4).equals(perms[i][j+1].substring(0, 2)))  
 check= false;  
 }  
 if(check)  
 return true;  
 }  
 return false;  
 }  
 public static boolean isCycle(int[] arr){  
 String[] s = new String[arr.length];  
 for (int i = 0; i &lt; s.length; i++)  
 s[i]=arr[i]+"";  
 String[][] perms = new String[(int)iFact(arr.length)][arr.length];  
 permute(perms,0,s,0);  
 for (int i = 0; i &lt; perms.length; i++) {  
 boolean check = true;  
 for (int j = 0; j &lt; perms[i].length; j++) {  
 if(j == perms[i].length-1){  
 if(!perms[i][j].substring(2, 4).equals(perms[i][0].substring(0, 2)))  
 check= false;  
 continue;  
 }  
 if(!perms[i][j].substring(2, 4).equals(perms[i][j+1].substring(0, 2)))  
 check= false;  
 }  
 if(check)  
 return true;  
 }  
 return false;  
 }  
 public static int permute(String[][] perms, int pc, String[] original, int a){  
 if(a==original.length-2){  
 perms[pc++] = original.clone();  
 swap(original,original.length-1,original.length-2);  
 perms[pc++] = original.clone();  
 return pc;  
 }  
 ArrayList list = new ArrayList();  
 for(int c = a ; c &lt; original.length;c++)  
 list.add(original[c]);  
 while(!list.isEmpty()){  
 String t = list.remove(0);  
 if(!t.equals(original[a]))  
 swap(original,a,find(original,t));  
 pc=permute(perms,pc,original,a+1);  
 }  
 return pc;  
 }  
 public static int find(String[] t, String k){  
 for (int i = 0; i &lt; t.length; i++)  
 if(t[i].equals(k))  
 return i;  
 return -1;  
 }  
 public static void swap(T[] arr, int a, int b){  
 T t= arr[a];  
 arr[a] = arr[b];  
 arr[b] = t;  
 }  
 }  

lunes, 25 de abril de 2011

Grupos Lie

Esto es simetría:


Empecé por funciones especiales, y acabé en los grupos Lie. Un día normal viendo artículos de física y matemáticas en wikipedia jojo.

miércoles, 23 de marzo de 2011

Smith chart



Aparte de ser muy funcional para análisis de líneas de transmisión, se ve chido.

martes, 22 de marzo de 2011

netping.bat

Y bueno, para aquellos que pensaban que el bash scripting no existía en windows, los tendré que probar mal. Aunque es cierto que es medio raro, y no soporta casi nada, se pueden hacer scripts rápidamente, una vez se conoce la sintáxis.

Esta vez lo que hice fue un programa que recorre todas las dirs IP en un octeto y devuelve si se respondió el ping. Una manera muy rápida y simple de ver qué IP están ocupados en la subred. Bueno les dejo el script:

:: Author: Andrés Páez Martínez paezand@gmail.com

:: Uso - netping [octetos a recorrer] [dirección IP acortada]
:: octetos puede ser 1 o 2.
:: Dir. IP varía si es 1 octeto o dos.
:: Por ejemplo,
:: netping 1 192.168.0
:: netping 2 192.168
:: NOTA - Netping se tarda aprox. 0.3 segs. por dirección. Por lo tanto dos octetos se tarda como 5 horas


@echo off

::Detecta qué octeto fue de input %1 = primer input
IF "%1"=="1" echo One octet on && goto ONE
IF "%1"=="2" echo Two octets on && goto TWO

:ONE
:: Detecta si hubo input, pero no si hubo error en el input
IF "%2"=="" echo Three octets necessary && goto END
echo pinging net
::var es la variable como contador dentro del loop (e.g for(int var=255;var!=0;var--))
set var=255

:LOOP1
set "a=%2%."
set a=%a%%var%
:: EL comando core del script, hace ping, luego busca el string "ttl=" en lo que
:: devuelve ping. Si lo encuentra
:: entonces imprime la dir. ip seguida por "is up", sino lo mismo pero con down.
ping -w 500 -n 1 %a% | findstr "TTL=">NUL && echo %a% is up || echo %a% is down
set /a var=%var%-1
if not %var%==0 goto LOOP1
goto END

:: Lo mismo que one pero con un loop anidado
:TWO
IF "%2"=="" echo Two octets necessary && goto END
echo pinging net
set var=255
:LOOP2a
set var1=255
:LOOP2b
set "a=%2%."
set "a=%a%%var%.%var1%"
ping -w 500 -n 1 %a% | findstr "TTL=">NUL && echo %a% is up || echo %a% is down
set /a var1=%var1%-1
if not %var1%==0 goto LOOP2b
set /a var=%var%-1
if not %var%==0 goto LOOP2a


:END

PAUSE