martes, febrero 17, 2009

project euler - problema 4

Ahora que me hice un tiempo encare el cuarto ejercicio, facil, pero me costo sacarme de la cabeza tratar de hacer todo en lisp con recursion y usar el macro loop (que por cierto es el mas poderozo que he visto en cualquier lenguaje).

algunas cosas para observar:

no se si soy yo, pero usar progn y setq en lisp no me convence, siempre pense al principio en hacer todo recursivo y con let, pero parece que se complica a veces (no conozco una forma de evitar los lets nesteados, debe haber una forma pero no la conozco).

en cuanto a erlang no me gusta la diferencia de and andalso y or y orelse, pero parece que esta ahi por razones historicas, el pattern matching es adictivo, no me gusta que no pueda poner ; en el ultimo guard de un case.

hasta ahora vengo resolviendo el problema primero en python, despues en erlang y despues en lisp, por ahi eso condiciona la forma en la que lo resuelvo, pero siempre trato de usar la solucion que mas se adapta al lenguaje.

aca va el codigo

python

def is_palindromic(number):
'''return True if the number is a palindrome'''
number = str(number)

limit_start = len(number) / 2

if len(number) % 2 == 1:
limit_end = limit_start + 1
else:
limit_end = limit_start

return number[limit_start:] == number[:limit_end][::-1]

def get_largest_palindrome():
'''get the largest 3 digit palindrome'''
temp = 0

for i in range(999, 0, -1):
for j in range(i, 0, -1):
value = i * j
if is_palindromic(value):
if temp < value:
temp = value

return temp

print get_largest_palindrome()



lisp

(defun is-palindrome (num)
(progn
(setf str (format nil "~a" num))
(setf size (length str))
(setf first-half (truncate (/ size 2)))
(if (evenp size)
(setf second-half first-half)
; else
(setf second-half (+ first-half 1)))
(equal (subseq str 0 first-half) (reverse (subseq str second-half size)))))

(defun get-largest-palindrome ()
(progn
(setf temp 0)
(loop for i from 999 downto 0 do
(loop for j from i downto 0 do
(progn
(setq value (* i j))
(if (and (is-palindrome value) (> value temp))
(setq temp value)))))
temp))

(print (get-largest-palindrome))



erlang

-module(ej_004).
-compile(export_all).
%-export([get_largest_palindrome/0]).

is_palindrome(Number) ->
String = integer_to_list(Number),
Size = string:len(String),
FirstHalf = Size div 2,

case Size rem 2 == 1 of
false -> SecondHalf = FirstHalf + 1;
true -> SecondHalf = FirstHalf + 2
end,

FirstPart = string:substr(String, 1, FirstHalf),
SecondPart = lists:reverse(string:substr(String, SecondHalf, Size)),

FirstPart == SecondPart.

get_largest_palindrome(0, 0, Accum) -> Accum;
get_largest_palindrome(X, 0, Accum) -> get_largest_palindrome(X - 1, X - 1, Accum);

get_largest_palindrome(X, Y, Accum) ->
Value = X * Y,

case is_palindrome(Value) andalso Value > Accum of
true -> NewValue = Value;
false -> NewValue = Accum
end,

get_largest_palindrome(X, Y - 1, NewValue).

get_largest_palindrome(X, Accum) -> get_largest_palindrome(X, X, Accum).
get_largest_palindrome() -> get_largest_palindrome(999, 0).

miércoles, febrero 11, 2009

project euler - problema 3

problema 3 y observaciones

el operador de modulo en erlang es muy poco intuitivo.

ej

1> 2.0 rem 2.
** exception error: bad argument in an arithmetic expression
in operator rem/2
called as 2.0 rem 2

si salta una excepcion en un guard en erlang no te dice que fue malo solo falla el guard

y alguna cosa mas que no me acuerdo.

python

import math

def factors(value):
factors = []
factor = 2.0
new_value = value
val_sqrt = math.sqrt(value)

while factor < val_sqrt:
if new_value % factor == 0:
factors.append(factor)
#new_value /= factor

factor += 1

return factors

def calculate(value):
return factors(value)[-1]

def print_results():
print calculate(600851475143)

if __name__ == '__main__':
print_results()


erlang

-module(ej_003).
-compile(export_all).

factors(Factor, _Value, Limit, Accum) when Factor > Limit -> lists:reverse(Accum);
factors(Factor, Value, Limit, Accum) when Value rem Factor == 0 ->
factors(Factor + 1, trunc(Value/Factor), Limit, [Factor | Accum]);
factors(Factor, Value, Limit, Accum) ->
factors(Factor + 1, Value, Limit, Accum).

factors(Value) -> factors(2, Value, trunc(math:sqrt(Value)), []).

print_results() ->
Factors = factors(600851475143),
io:format("~w~n", [Factors]),
if
length(Factors) > 0 -> io:format("~w~n", ([lists:last(Factors)]));
true -> io:format("No factor~n")
end.



lisp

(defun factors-helper (value limit)
(loop for factor from 2 when (= (rem value factor) 0) collect factor while (< factor limit)))

(defun factors (value) (factors-helper value (truncate (sqrt value))))

(defun print-results () (print (last (factors 600851475143))))

(print-results)

domingo, febrero 08, 2009

Keep Your Identity Small

http://www.paulgraham.com/identity.html

la conclusión esta buena.

But there is a step beyond thinking of yourself as x but tolerating y: not even to consider yourself an x. The more labels you have for yourself, the dumber they make you.

sábado, febrero 07, 2009

project euler - problema 2

La diferencia es que en python lo hice con generadores ya que queda mas prolijo, hasta donde se no hay generadores en los otros.

Python

# Each new term in the Fibonacci sequence is generated by adding the previous
# two terms. By starting with 1 and 2, the first 10 terms will be:
# 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
# Find the sum of all the even-valued terms in the sequence which do not
# exceed four million.

def fibonacci():
one = 0
two = 1
step = 1

while True:
one, two = two, one + two
yield two
step += 1

def calculate(limit):
result = 0
for value in fibonacci():
if value > limit:
break

if value % 2 == 0:
result += value

return result

def print_result():
print calculate(4000000)

if __name__ == '__main__':
print_result()



Erlang

-module(ej_002).
-compile(export_all).
%-export([calculate/1, print_result/0]).

fibonacci_step(First, Second) -> {Second, First + Second}.

calculate(First, Second, Limit) -> calculate(First, Second, Limit, 0).

calculate(_First, Second, Limit, Accum) when Second > Limit -> Accum;
calculate(First, Second, Limit, Accum) ->
{NewFirst, NewSecond} = fibonacci_step(First, Second),

case NewSecond rem 2 of
0 -> NewAccum = Accum + NewSecond;
1 -> NewAccum = Accum
end,

calculate(NewFirst, NewSecond, Limit, NewAccum).

calculate(Limit) -> calculate(0, 1, Limit).

print_result() -> io:format("~w~n", [calculate(4000000)]).


Lisp (note que los paréntesis dejan de molestar y si lo tabulas de una forma particular se parece mucho a python :D)

(defun fibonacci-step (one two)
(list two (+ one two)))

(defun calculate-helper (one two limit accum)
(cond ((> two limit) accum)
(T (let ((result (fibonacci-step one two)))
(let ((new-one (car result))
(new-two (cadr result)))

(if (eq (rem new-two 2) 0)
(calculate-helper new-one new-two limit (+ accum new-two))
(calculate-helper new-one new-two limit accum)))))))

(defun calculate (limit) (calculate-helper 0 1 limit 0))

(defun print-result () (print (calculate 4000000)))

viernes, febrero 06, 2009

project euler - problema 1

me cree una cuenta en project euler para aprender bien erlang y lisp, voy a intentar resolver todos los problemas en esos lenguajes y en python como lenguaje conocido para comparar los resultados. Obviamente esto es algo que voy a abandonar, la pregunta es cuando :D

No necesariamente voy a usar la misma forma, porque a veces no se puede o no la se, por ahora con tal que ande esta todo bien.

aca va el resultado del primer problema

python

# Add all the natural numbers below one thousand that are multiples of 3 or 5.

# If we list all the natural numbers below 10 that are multiples of 3 or 5,
# we get 3, 5, 6 and 9. The sum of these multiples is 23.
# Find the sum of all the multiples of 3 or 5 below 1000.

def calculate():
return sum(x for x in xrange(1000) if x % 3 == 0 or x % 5 == 0)

def print_result():
print calculate()

if __name__ == '__main__':
print_result()


en erlang

-module(ej_001).
-export([calculate/0, print_result/0]).

calculate() -> lists:sum([X || X <- lists:seq(0, 1000), X rem 3 == 0 orelse X rem 5 == 0]).

print_result() -> io:format("~w~n", [calculate()]).


en lisp

(defun multiple-of-3-or-5 (value)
(or (eq (rem value 3) 0)
(eq (rem value 5) 0))
)

(defun calculate-helper (value accum limit)
(cond ((= value limit)
accum)
((multiple-of-3-or-5 value)
(calculate-helper (+ value 1) (+ accum value) limit))
(T
(calculate-helper (+ value 1) accum limit))
)
)

(defun calculate () (calculate-helper 0 0 1000))

(defun print-result ()
(print (calculate)))

(print-result)

jueves, febrero 05, 2009

Llega un momento en la vida de todo hombre...

en la que uno crea una distribución live basada en ubuntu

mi primer distro live, creada para probar y para ayudar a pyar en su proyecto de difusión del lenguaje, contiene un escritorio liviano (openbox + fbpanel) y un conjunto de herramientas para el desarrollo del lenguaje, entre ellas:

Interpretes
  • python 2.4
  • python 2.5
  • python 3.0
  • ipython
Editores
  • gedit
  • vim
  • emacs
  • scribes
IDEs

  • Geany
  • Glade-3 (no es una ide del todo)
Otros

  • gnome-terminal
  • thunar
  • obconf (para configurar openbox)
  • openbox
  • fbpanel
  • sqlite3
  • NetworkManager
  • firefox
cosas que le faltan

  • agregarle localización a español
  • agregarle una pagina de inicio a firefox con links a la documentación local
  • la documentación local
  • frameworks web
la iso pesa en este momento 387 MB así que hay bastante espacio para seguir poniendo cosas.

como siempre, acá van los screenshots:





recien arrancado


todos los interpretes


todos los editores


geany + documentacion



Thunar, firefox y la configuracion de open box


glade-3

domingo, febrero 01, 2009

Quotes

PHP is a minor evil perpetrated and created by incompetent amateurs, whereas Perl is a great and insidious evil perpetrated by skilled but perverted professionals.

Engineers are all basically high-functioning autistics who have no idea how normal people do stuff.
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind.

he idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.

Never trust a programmer in a suit.


sábado, enero 31, 2009

E E E E Enterprise!

  • Estas parseando metadatos de imagenes en tu super enterprise entorno java
  • le tiras un XPath al Nodo de los metadatos que te devuelve la API y no te devuelve nada
  • pensas "debe estar mal la query XPath"
  • lo probas en un debugger de XPath y anda
  • le das mil vueltas y sigue sin andar
  • probas con DOM a mano (que es una API horrenda) y anda
  • pero te negas a hacerlo en DOM pelado
  • seguis probando
  • "no puede ser que la API esta mal" pensas
  • ya te rendis y le preguntas a google
  • "This class is not intended to be used for general XML processing. In particular, Element nodes created within the Image I/O API are not compatible with those created by Sun's standard implementation of the org.w3.dom API. In particular, the implementation is tuned for simple uses and may not perform well for intensive processing."
  • Intensive processing? no responde a los queries XPath, eso no es intensive, eso es mal implementado!
  • lo siguiente lo dijo mejor este vago que lo que podria escribir yo asi que lo cito
"I can understand that IIOMetadataNode may be a subset of what is
possible in a org.w3.dom.Node, but that does not mean it should
actually be wrong. Since javax.imageio.metadata.IIOMetadata.
getAsTree() returns an org.w3.dom.Node, I believe that compliance
with the contract for org.w3.dom.Node is required.

In the case of the JPEG 2000 metadata accessed using this method,
I have observed Nodes of type Element with Values set, which is
illegal.

If Element nodes are not going to have Text children in your model,
then they should have Attribute children with the Attribute name
being "value", and I don't think the JPEG 2000 metadata is doing
that (unlike the standard metadata which does use Attributes).

Also, it is all very well to say that the IIOMetadataNode is not
a "real" Node, but the point of choosing this methodology was so
as to allow the use of "ordinary" style DOM accessors, at least
that is how I remember the decision in the JSR 015 Expert Group
discussions. It is presumably the point of the existence of the
getAsTree() method.

To that end, if an ordinary Transformer cannot render the structure
returned by getAsTree() as XML without losing information, and if
XPath cannot query it, then I would argue that the implementation
of getAsTree() is broken, not just limited.

The "ability to store an Object reference within a node" is all
very well in special circumstances, but should NOT in my opinion,
be abused just to point to a scalar type, for example. This begs
the question of what the behavior is supposed to be, or defined
to be, for javax.imageio.metadata.IIOMetadata.getAsTree() in
such circumstances. Not that I have looked into the detail of
how this is implemented, just wondering theoretically how such
an Object reference would be correctly used and under what use
cases it is required."

http://forums.java.net/jive/thread.jspa?messageID=255691

y el problema es que esto ya me paso antes, en la api del widget para mostrar Rich Text en swing no hay forma en la api para obtener el offset del cursor contando el HTML que esta por detras, solo te da el offset del texto que esta en pantalla, por lo tanto hay muchas acciones que se re complican, buscando en los foros por esa epoca habia respuestas como "si, sabemos que esta mal pero no lo vamos a arreglar por X o por Y".

muy enterprise..

Edit 1:

  • por que no puedo iterar sobre un NodeList en ese pseudo foreach que tienen? es un iterable despues de todo no?
  • porque Vector no tiene una api para hacer slicing?
  • porque Vector, LinkedList y ArrayList son implementaciones de List? no podrian esconder los detalles de implementacion al usuario y hacerles pensar que estan eligiendo mal cada vez que eligen uno por sobre el otro?
  • Porque Vector es thread safe y LinkedList y ArrayList no?
  • La version limitada de Node que me devuelve la metadata de la imagen no me deja hacer getElementByTagName, asi que no puedo hacer mas que iterar por todos los childs buscando el que me hace falta ya que por suerte en la implementacion se mueve de posicion.
  • size() length() getLength() getSize(), no se ponen de acuerdo en eso no?
demasiado por hoy

domingo, enero 25, 2009

Igualdad

La igualdad entre el hombre y la mujer sera un hecho el día que las mujeres entiendan y admitan que el molinete en el metegol va en contra del sacrosanto deporte y dejen de ejercerlo por propia voluntad.

maldito burgues


Lo mas extremo que hice esta semana fue correr el bondi una cuadra escuchando fun people




ya que estamos les dejo una canción y una letra de fun people.

(noten la capacidad del vago para meter esa letra en ese ritmo)

Imposible es rescatar volver a vivir ciertos momentos si por un desengaño juntaste mucha bronca y si por
un desengaño juntaste mucha rabia pero vamos que nada es para tanto y tanto no lo es todo, ante todo con
firmeza mantiene tu espiritu con humor vence tus tabues deja atras tu timidez si en verdad lo nesesitas ve a
buscar lo que te gusta no te engañes no te mientas que nada es para tanto y tanto no lo es todo ante todo y
con firmeza mantiene tu espiritu con humor.


jueves, enero 22, 2009

domingo, enero 18, 2009

X=?

El X supone la defensa radical y consecuente de la libertad. El X correctamente entendido es equivalente al liberalismo. La sociedad libre y ética es la basada en la propiedad privada y los contratos, donde ninguna persona o grupo de personas está legitimado para agredir a otros. La sociedad no tiene derecho a forzar a los individuos.

X es una de las palabras mas mal usadas que conozco.

me gusto esa definición.

jueves, enero 08, 2009

PHP vs web.py (cgi) vs python cgi en dreamhost

estoy indeciso sobre que usar para un proyectito web que tengo en mente, el hosting es dreamhost, y debido a que tiene la limitacion de 100MB de RAM por proceso python en fastcgi (cosa que no tiene ruby on rails :S), decidi probar las alternativas.

probe un hola mundo en PHP, web.py y un script de python pelado.

tanto web.py y el script son servidos por un apache con mod_rewrite, todos hacen lo mismo, que es imprimir "hola mundo!", los resultados son los siguientes:

para php

ab -c 4 -n 300 http://www.marianoguerra.com.ar/php/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.marianoguerra.com.ar (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Finished 300 requests


Server Software: Apache/2.2.9
Server Hostname: www.marianoguerra.com.ar
Server Port: 80

Document Path: /php/
Document Length: 12 bytes

Concurrency Level: 4
Time taken for tests: 28.272 seconds
Complete requests: 300
Failed requests: 0
Write errors: 0
Total transferred: 72980 bytes
HTML transferred: 3600 bytes
Requests per second: 10.61 [#/sec] (mean)
Time per request: 376.961 [ms] (mean)
Time per request: 94.240 [ms] (mean, across all concurrent requests)
Transfer rate: 2.52 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 24 33 10.1 30 93
Processing: 272 342 91.5 315 929
Waiting: 267 334 90.4 308 913
Total: 298 375 93.3 347 976

Percentage of the requests served within a certain time (ms)
50% 347
66% 365
75% 387
80% 398
90% 446
95% 562
98% 738
99% 844
100% 976 (longest request)

para web.py

ab -c 4 -n 300 http://www.marianoguerra.com.ar/py/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.marianoguerra.com.ar (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Finished 300 requests


Server Software: Apache/2.2.9
Server Hostname: www.marianoguerra.com.ar
Server Port: 80

Document Path: /py/
Document Length: 13 bytes

Concurrency Level: 4
Time taken for tests: 84.578 seconds
Complete requests: 300
Failed requests: 0
Write errors: 0
Total transferred: 65100 bytes
HTML transferred: 3900 bytes
Requests per second: 3.55 [#/sec] (mean)
Time per request: 1127.711 [ms] (mean)
Time per request: 281.928 [ms] (mean, across all concurrent requests)
Transfer rate: 0.75 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 24 32 7.1 30 89
Processing: 423 1095 485.1 981 2824
Waiting: 422 1094 485.1 980 2821
Total: 454 1127 484.6 1012 2851

Percentage of the requests served within a certain time (ms)
50% 1012
66% 1222
75% 1375
80% 1483
90% 1829
95% 2212
98% 2481
99% 2660
100% 2851 (longest request)


para python cgi

ab -c 4 -n 300 http://www.marianoguerra.com.ar/picgi/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.marianoguerra.com.ar (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Finished 300 requests


Server Software: Apache/2.2.9
Server Hostname: www.marianoguerra.com.ar
Server Port: 80

Document Path: /picgi/
Document Length: 323 bytes

Concurrency Level: 4
Time taken for tests: 19.617 seconds
Complete requests: 300
Failed requests: 0
Write errors: 0
Non-2xx responses: 300
Total transferred: 173100 bytes
HTML transferred: 96900 bytes
Requests per second: 15.29 [#/sec] (mean)
Time per request: 261.559 [ms] (mean)
Time per request: 65.390 [ms] (mean, across all concurrent requests)
Transfer rate: 8.62 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 24 32 7.4 30 81
Processing: 212 229 25.5 226 440
Waiting: 212 228 25.5 225 440
Total: 240 261 26.4 256 468

Percentage of the requests served within a certain time (ms)
50% 256
66% 260
75% 263
80% 265
90% 274
95% 283
98% 325
99% 463
100% 468 (longest request)

conclusion

una porqueria que dreamhost ponga ese limite a fastcgi, es explicable que web.py demore, ya que tiene que levantar el interprete e importar todo el framework cada vez que lo llamo solo para mostrar un hola mundo. Lo que me sorprende es que python/cgi pelado sea mas rapido que php, siendo que python tiene que levantar el interprete cada vez.
Aclaro que este microbenchmark comprueba realmente cuanto tarda en servir una peticion y no compara la velocidad de los lenguajes en si, pero eso es lo que me interesa, ya que python le pasa el trapo a php en performance :P http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=python&lang2=php

en resumen, no se si hacerlo en python en este host, ya que sacrificar el beneficio de un framework por una limitacion del hosting es un perno :S

miércoles, enero 07, 2009

Sonido, Wireless y flash en FreeBSD 7.1

Bueno, logre hacer andar todos, el unico que no quedo bien fue flash

para instalar flash compile gnash

cd /usr/ports/graphics/gnash
make install

todo bonito se carga el plugin, pero no puedo ver videos ni de youtube, ni de vimeo ni de blip.tv, asi que le falta a gnash para ser usable.

para el sonido segui las instrucciones del handbook de freebsd y salio andando como piña.

http://www.freebsd.org/doc/en/books/handbook/sound-setup.html

para la wireless segui el manual pero me faltaba algo, asi que lei la referencia de wpa_supplicant, aca estan los links

http://www.freebsd.org/doc/en/books/handbook/network-wireless.html

http://www.daemon-systems.org/man/wpa_supplicant.conf.5.html

todo parece estar andando seguire peleando :D

probando FreeBSD 7.1

Es la tercera vez que le doy una probada a FreeBSD, primero fue la 6.3, despues la 7.0 y ahora la 7.1, me baje el DVD de los torrents y empece de nuevo con todo lo que me había olvidado.

observaciones:
* el instalador es igual al 6.3, se podría hacer un poco mas simple incluso para los geeks ocultando preguntas que tienden a ser defaults todo el tiempo excepto raras excepciones, fuera de eso, si peleaste contra debian, no te va a sorprender nada.

* una vez instalado, no instale el bootloader para dejar grub y tuve que poner una entrada en el grub que fue distinta a las anteriores, en este caso fue:

title Free-BSD
root (hd0,2)
chainloader +1
boot

* como siempre, no me reconoció ni el sonido, ni la wireless, pero esta vez le sumo el touchpad, que la ultima vez me lo había reconocido, para solucionarlo seguí estos pasos y anduvieron a la perfección.

http://fixunix.com/xwindows/383881-how-use-alps-glidepoint-touchpad-xorg-7-3-freebsd-7-0-release-amd64.html

un poco mas de info acá

http://wiki.freebsd.org/SynapticsTouchpad

* no recuerdo de la ultima vez, pero tuve que escribir el .xinitrc a mano y correr xorgconfig para generar el xorg.conf, me hizo preguntas muchas mas técnicas que las que hacia dpkg-reconfigure xserver-xorg en ubuntu.

* a pesar de instalar sudo y tener una sola cuenta fuera de root, me tuve que agregar en /usr/local/etc/sudoers con la entrada

mariano ALL=(ALL) ALL

* como siempre también tuve que correr sudo vipw para cambiar el shell fiero que tiene por defecto por el querido bash, recuerden que aca no es /bin/bash sino /usr/local/bin/bash

* feo que tenga firefox 2.0.20

* todavía me tengo que poner a pelear con el sonido, la wireless y como siempre, flash...

del lado bueno

* los ports son algo que se extraña de gentoo
* aguante FreeBSD :D

martes, enero 06, 2009

Are my ideas being stolen?

de un articulo de slashdot sale el siguiente comentario

http://ask.slashdot.org/comments.pl?sid=1082003&cid=26345371

In "The Zen of Graphics Programming", Michael Abrash (a co-author of Quake and inventor of Mode X) wrote:

-------------
Our world is changing, and I'm concerned. By way of explanation, three anecdotes.

Anecdote the first: In one of his books, Frank Herbert, author of Dune, told me how he had once been approached by a friend who claimed he (the friend) had a killer idea for a SF story, and offered to tell it to Herbert. In return, Herbert had to agree that if he used the idea in a story, he'd split the money from the story with this fellow. Herbert's response was that ideas were a dime a dozen; he had more story ideas than he could ever write in a lifetime. The hard part was the writing, not the ideas.

Anecdote the second: I've been programming micros for 15 years, and been writing about them for more than a decade and, until about a year ago, I had never-not once!- had anyone offer to sell me a technical idea. In the last year, it's happened multiple times, generally via unsolicited email along the lines of Herbert's tale.

This trend toward selling ideas is one symptom of an attitude that I've noticed more and more among programmers over the past few years-an attitude of which software patents are the most obvious manifestation-a desire to think something up without breaking a sweat, then let someone else?s hard work make you money. Its an attitude that says, "I'm so smart that my ideas alone set me apart." Sorry, it doesn't work that way in the real world. Ideas are a dime a dozen in programming, too; I have a lifetime's worth of article and software ideas written neatly in a notebook, and I know several truly original thinkers who have far more yet. Folks, it's not the ideas; it's design, implementation, and especially hard work that make the difference.

Virtually every idea I've encountered in 3-D graphics was invented decades ago. You think you have a clever graphics idea? Sutherland, Sproull, Schumacker, Catmull, Smith, Blinn, Glassner, Kajiya, Heckbert, or Teller probably thought of your idea years ago. (I'm serious-spend a few weeks reading through the literature on 3-D graphics, and you'll be amazed at what's already been invented and published.) If they thought it was important enough, they wrote a paper about it, or tried to commercialize it, but what they didn't do was try to charge people for the idea itself.

A closely related point is the astonishing lack of gratitude some programmers show for the hard work and sense of community that went into building the knowledge base with which they work. How about this? Anyone who thinks they have a unique idea that they want to "own" and milk for money can do so-but first they have to track down and appropriately compensate all the people who made possible the compilers, algorithms, programming courses, books, hardware, and so forth that put them in a position to have their brainstorm.

Put that way, it sounds like a silly idea, but the idea behind software patents is precisely that eventually everyone will own parts of our communal knowledge base, and that programming will become in large part a process of properly identifylng and compensating each and every owner of the techniques you use. All I can say is that if we do go down that path, I guarantee that it will be a poorer profession for all of us - except the patent attorneys, I guess.

Anecdote the third: A while back, I had the good fortune to have lunch down by Seattle's waterfront with Neal Stephenson, the author of Snow Crash and The Diamond Age (one of the best SF books I've come across in a long time). As he talked about the nature of networked technology and what he hoped to see emerge, he mentioned that a couple of blocks down the street was the pawn shop where Jimi Hendrix bought his first guitar. His point was that if a cheap guitar hadn't been available, Hendrix's unique talent would never have emerged. Similarly, he views the networking of society as a way to get affordable creative tools to many people, so as much talent as possible can be unearthed and developed.

Extend that to programming. The way it should work is that a steady flow of informa-tion circulates, so that everyone can do the best work theyre capable of. The idea is that I don't gain by intellectually impoverishing you, and vice-versa; as we both compete and (intentionally or otherwise) share ideas, both our products become better, so the market grows larger and everyone benefits.

That's the way things have worked with programming for a long time. So far as I can see it has worked remarkably well, and the recent signs of change make me concerned about the future of our profession.

viernes, diciembre 26, 2008

Haganme un favor

Cuando estén con migo ponganme en una situación en la que pueda decir touche de manera adecuada.

Siempre quise parecer inteligente diciendo esa palabra

Book meme

Ningún Test lo es. - Sueñan los androides con ovejas eléctricas? Philip K. Dick
link: http://fitoria.net/2008/11/13/book-meme/
  • Agarra el libro mas cercano
  • Abrelo en la pagina 56.
  • Encuentra la quinta oración.
  • Postealo junto con estas instrucciones
  • No vayas por tu libro favorito solo agarra el que este MAS CERCA
  • Poner la url del site donde leíste el meme

lunes, diciembre 22, 2008

Xml -> dict -> objetos

En este ejemplo se muestra como convertir un string a una estructura de diccionarios y listas anidadas usando expat, tambien se proveen dos clases que permiten manipular el resultado como si fueran objetos.

primero el codigo

import xml.parsers.expat

class XmlParser(object):
'''a class that parses a xml string an generates a nested
dict/list structure
'''

def __init__(self, text):
'''constructor'''
self.parser = xml.parsers.expat.ParserCreate()
self.parser.buffer_text = True

self.result = None
self.stack = []
self.current = None

self.parser.StartElementHandler = self.start_element
self.parser.EndElementHandler = self.end_element
self.parser.CharacterDataHandler = self.char_data
self.parser.Parse(text)

def start_element(self, name, attrs):
'''Start xml element handler'''
if self.current != None:
self.stack.append(self.current)

self.current = {}

for (key, value) in attrs.iteritems():
self.current[str(key)] = value

self.current['tag'] = name
self.current['childs'] = []

def end_element(self, name):
'''End xml element handler'''
if len(self.stack):
current = self.stack.pop()
current['childs'].append(self.current)
self.current = current
else:
self.result = self.current

def char_data(self, data):
'''Char xml element handler.
buffer_text is enabled, so this is the whole text element'''
self.current['childs'].append(data)

class DictObj(dict):
'''a class that allows to access a dict as an object
'''

def __init__(self, kwargs):
'''constructor'''
dict.__init__(self, kwargs)

def __getattribute__(self, name):
if name in self:
obj = self[name]

if type(obj) == dict:
return DictObj(obj)
elif type(obj) == list:
return ListObj(obj)

return obj
else:
return None

class ListObj(list):
'''a class that allows to access dicts inside a list as objects
'''

def __init__(self, args):
'''constructor'''
list.__init__(self, args)

def __getitem__(self, index):
if index > len(self):
raise IndexError('list index out of range')

obj = list.__getitem__(self, index)

if type(obj) == dict:
return DictObj(obj)
elif type(obj) == list:
return ListObj(obj)

return obj

def __iter__(self):
'''iterate over the list'''

count = 0

while count < len(self):
yield self[count]
count += 1

def raw_string(dct_):
'''return a string containing just the string parts removing all the
xml stuff'''

def helper(dct):
result = []

for child in dct.childs:
if type(child) == str or type(child) == unicode:
result.append(str(child))
else:
result = result + helper(child)

return result

return ''.join(helper(dct_))



Simplemente creamos un objeto de tipo XmlParser pasandole el string y obtenemos el resultado parseado en la variable result. Si no queremos andar preguntado si las llaves existen antes de accederlas para evitar excepciones podemos usar la clase DictObj que nos permite acceder a las llaves como si fueran atributos, las variables que no existan como llaves contendran None. Aca va un ejemplo en la consola interactiva


>>> import XmlParser
>>> p = XmlParser.XmlParser('google test foo !!')
>>> r = p.result
>>> d = XmlParser.DictObj(r)
>>> d
{'childs': [{'childs': [u'go', {'childs': [u'o'], 'tag': u's'}, u'gle'], 'href': u'google.com', 'tag': u'a'}, u' ', {'childs': [u'test'], 'tag': u'i'}, u' ', {'childs': [], 'src': u'foo.png', 'alt': u'foo', 'tag': u'img'}, u' ', {'childs': [u'!'], 'tag': u'u'}, {'childs': [u'!'], 'tag': u's'}], 'tag': u'span'}
>>> d.childs
[{'childs': [u'go', {'childs': [u'o'], 'tag': u's'}, u'gle'], 'href': u'google.com', 'tag': u'a'}, u' ', {'childs': [u'test'], 'tag': u'i'}, u' ', {'childs': [], 'src': u'foo.png', 'alt': u'foo', 'tag': u'img'}, u' ', {'childs': [u'!'], 'tag': u'u'}, {'childs': [u'!'], 'tag': u's'}]
>>> d.childs[0]
{'childs': [u'go', {'childs': [u'o'], 'tag': u's'}, u'gle'], 'href': u'google.com', 'tag': u'a'}
>>> d.childs[0].tag
u'a'
>>> d.childs[0].childs[0]
u'go'
>>> d.childs[0].childs[1].tag
u's'

jueves, diciembre 18, 2008

Metacrap

buen articulo (explica por que nunca use los tags de blogger :P)

http://www.well.com/~doctorow/metacrap.htm

sábado, diciembre 13, 2008

sobre startups

este articulo confirma algunas cosas que tenia en mente y que no sabia si era yo nomas :D

http://www.paulgraham.com/divergence.html

quotes para los fiacosos

The reason startups no longer depend so much on VCs is one that everyone in the startup business knows by now: it has gotten much cheaper to start a startup. There are four main reasons: Moore's law has made hardware cheap; open source has made software free; the web has made marketing and distribution free; and more powerful programming languages mean development teams can be smaller. These changes have pushed the cost of starting a startup down into the noise.

Once you cross the threshold of profitability, however low, your runway becomes infinite. It's a qualitative change, like the stars turning into lines and disappearing when the Enterprise accelerates to warp speed. Once you're profitable you don't need investors' money. And because Internet startups have become so cheap to run, the threshold of profitability can be trivially low. Which means many Internet startups don't need VC-scale investments anymore.

jueves, diciembre 04, 2008

import antigravity

problema: queres pasarle uno o mas archivos a una persona, solo queres que vea archivos de una carpeta determinada y poner apache o samba no tiene sentido para vos.

solucion en una linea de python:

__import__('BaseHTTPServer').HTTPServer(('', 8000), __import__('SimpleHTTPServer').SimpleHTTPRequestHandler).serve_forever()


si lo queres correr desde la consola (te publica el directorio donde corriste el comando):

python -c "__import__('BaseHTTPServer').HTTPServer(('', 8000), __import__('SimpleHTTPServer').SimpleHTTPRequestHandler).serve_forever()"


vamos a admitirlo, es un poco perlish, asi que vamos a ponerlo mas limpio:

import BaseHTTPServer
import SimpleHTTPServer

server = BaseHTTPServer.HTTPServer(('', 8000), SimpleHTTPServer.SimpleHTTPRequestHandler)
server.serve_forever()



PD: al final lo pasamos en pendrive porque eran 899MB pero cuando haces algo asi en python es con el unico fin de levantarte minas, ej:

*se aproxima a la mujer objetivo en bar, boliche o similar*
- ayer le tenia que pasar un archivo a un amigo y no tenia como
*hace gesto de desinteresada*
- sabes que hice?
*no responde*
*mira para otro lado*
- escribi un servidor web en 4 lineas de python
*lo mira*
*comienza a besarlo apasionadamente*

;)

sábado, noviembre 29, 2008

Workaround

este post es un placeholder, cuando quieras sharear una url que no tenes en tus links podes ir al feed de mi blog (obviamente lo tenes en los feeds :P) y shareas este post con un comentario con la url que te parecio interesante.

Esto hasta que google reader me permita sharear urls arbitrarias sin tener que estar suscripto a su feed.

Si el post te parece muy largo puedo crear uno sin toda esta explicacion, pero esta bueno que tu share tenga la explicacion de porque estas shareando un post tan pedorro con una url que no tiene nada que ver :D

Si tildas este post como "keep unread" en reader no vas a tener que tener "all items" en mi blog, sino que solo vas a poder ver los nuevos ;)

a su servicio,
wariano

miércoles, noviembre 26, 2008

How Software Companies Die

"Programming is the Great Game. It consumes you, body and soul. When you're caught up in it, nothing else matters. When you emerge into daylight, you might well discover that you're a hundred pounds overweight, your underwear is older than the average first grader, and judging from the number of pizza boxes lying around, it must be spring already. But you don't care, because your program runs, and the code is fast and clever and tight. You won. "

http://www.zoion.com/~erlkonig/writings/programmer-beekeeping.html

martes, noviembre 18, 2008

vimrc

set nocompatible
set smartcase
set incsearch
set hlsearch
set bs=indent,eol,start
set ts=4
set sts=4
set sw=4
set et
set tw=75
set ai
set smartindent
set smarttab
set syntax

# estas 3 son para gvim en windows

colorscheme desert
set guioptions-=T
set guifont=Consolas:h14

lo dejo para que cada vez que tenga un vim al frente tenga las settings que uso siempre en algún lado, si le sirve a alguien bien :D

martes, noviembre 11, 2008

miércoles, noviembre 05, 2008

lunes, octubre 27, 2008

minirants

1) a mi que me da verguenza cuando emesene se congela por unos segundos, la verguenza que deben pasar los de outlook que se congela todo el tiempo :P

2) aguante la opcion -c de wget

jueves, octubre 16, 2008

migrar access a postgres

aca hay un pequeño script que hice para migrar de access a postgres, tuve que hacer algunos trucos para que ande bien. si a alguien le sirve...
import os
import commands

archivo = "archivo.mdb"

tables = commands.getoutput("mdb-tables -S %s" % (archivo,))
os.popen("rm carga.sql")
os.popen("rm schema.sql")

os.popen("mdb-schema -S %s postgres| sed 's/Postgres_Unknown 0x0c/Text/' | grep \"\-\-\" -v | grep \"^DROP TABLE\" -v | sed 's/Bool/Int8/' > schema.sql" \
% (archivo,))

for table in tables.split():
cmd = \
# si tenes el postgres con locales que te pide insertar la fecha con un
# formato no ISO (MDY) correr la siguiente linea antes de los inserts
# SET DateStyle TO 'MDY';
"mdb-export -I -S %s %s | sed -e 's/)$/)\;/' | sed -e s/\\\"/\\'/g >> carga.sql"
if not table.startswith('MSys'):
os.popen(cmd % (archivo, table))

domingo, octubre 12, 2008

cosas locas de java

en una clase tengo dos atributos privados, los cuales solo son modificados por un método. Hasta ahí todo bien.
El problema es que para poder serializar esa clase a json y para poder guardarla en Hibernate tienen que ser beans (osea esos atributos tienen que tener getter y setters) por lo cual me rompe todo el bendito encapsulamiento, ya que cualquiera manipulando un objeto puede romper la consistencia y relacion de los dos atributos usando el set de uno (no, no puedo deducir que hacer con el otro en base al valor de uno).

Cosas que pasan.

PD: puede que haya una forma de arreglarlo, yo no la se.

jueves, octubre 02, 2008

Quote

And do you have any advice for up-and-coming programmers? I think it’s important to try to master the different paradigms of programs that are out there. The obvious object oriented programming is hopefully something that you will be taught in school. Hopefully school will also teach you functional programming, if not, that is a good thing to go look at.

Go look at dynamic languages and meta-programming: those are really interesting concepts. Once you get an understanding of these different kinds of programming and the philosophies that underlie them, you can get a much more coherent picture of what’s going on and the different styles of programming that might be more appropriate for you with what you’re doing right now.

Anyone programming today should check out functional programming and meta-programming as they are very important trends going forward.

del creador de C#

lunes, septiembre 29, 2008

Quote de pyar

by juanjo conti

>> Esto quiere decir que ya podrán competir programadores de C# y java.
>>
>
> Los amigos no dejan que los amigos programen en Java.

viernes, septiembre 26, 2008

Yahoo test

desde hoy voy a usar yahoo como mi buscador por defecto en firefox en todas mis maquinas.
En una semana aprox les comento los resultados.

miércoles, septiembre 10, 2008

ultimo tweet (?)

@LHC: No, YOU suck!

si lo lees mañana va a ser un chiste totalmente pasado de moda.

para cuando el proximo meme con ribetes cientificos?

viernes, septiembre 05, 2008

tiernizzzz ^^

Frente a todos los estereotipos, los aficionados al "heavy metal" son personas tiernas, según un estudio divulgado hoy en el Reino Unido que analiza los vínculos entre los gustos musicales y los rasgos de la personalidad.

De acuerdo con la investigación, tanto los amantes del jazz como los de la música clásica tienen una alta autoestima y son gente creativa, pero mientras los primeros se caracterizan por su sociabilidad, los segundos son personas introvertidas.

yo escucho jazz, musica clasica y metal de todo tipo, que demonios soy?

http://criticadigital.com/index.php?secc=nota&nid=10338

martes, septiembre 02, 2008

tweets teledirigidos

@fibertel: gracias por ponerme de mal humor el domingo, metete tus mensajes de bienvenida windows only que bloquean el acceso a donde mas te plasca
@jquery: (hasta ahora) gracias
@255.255.255.255: tengo router inhalambrico, las lan parties son cosa del pasado, wlan parties FTW

Seguidores

Archivo del Blog