Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre python (publicaciones antiguas, página 117)

Datos sobre nombres de Argentina

Ha­ce unos años pu­bli­qué una "a­pp" en http://­nom­bres.­ral­si­na.­me pa­ra ju­gar con la ba­se de da­tos ofi­cial de nom­bres de Ar­gen­ti­na. El RE­NA­PER ha­bía pu­bli­ca­do la lis­ta de nom­bres de pi­la y canti­dad de gen­te con ese nom­bre en ca­da año des­de 1922 has­ta 2015 y da­ba pa­ra ha­cer una co­si­ta di­ver­ti­da cu­yo uso prin­ci­pal ha si­do ha­cer­me el gra­cio­so en twi­tte­r.

Esos da­tos los sa­qué de acá y se usa­ban en es­ta pá­gi­na ... que ya no an­da

Pe­ro ... los da­tos es­tán pu­bli­ca­dos co­mo CS­V, y la ca­li­dad es muy ma­la, y pa­ra po­der usar­los hay que im­por­tar­los en una ba­se, y ha­cer bús­que­das cuan­do la or­to­gra­fía de los nom­bres es va­ria­ble es un lío y ...

Así que de­ci­dí pu­bli­car mi ba­se "lim­pia" en al­gu­na par­te, y ya que es­ta­mos tam­bién una co­pia de los da­tos ori­gi­na­le­s, pe­ro en una ba­se SQL que se pue­da usar di­rec­to.

Bus­can­do co­mo ha­cer­lo en­contré Dol­tHub que es "co­mo Gi­tHub pe­ro pa­ra da­to­s" así que de­ci­dí usar­lo.

Sin más pro­le­gó­me­no­s: http­s://www.­dol­thu­b.­co­m/­re­po­si­to­rie­s/­ral­si­na/­nom­bres_ar­gen­ti­na_1922_2005/­da­ta/­main

Gra­cias al RE­NA­PER por pu­bli­car es­tos da­tos con una li­cen­cia que me per­mi­te ha­cer­lo.

Lo que Ando Haciendo

Este post es una lista de "proyec­tos" en los que es­toy me­tien­do mano en es­tos tiem­pos. En otras épocas hu­biera si­do una lista de proyec­tos open source pero hoy en día es al­go bas­tante más di­ver­so.

NINGU­NA de las cosas que van a ver a con­tin­uación es un proyec­to "se­ri­o" o us­able para al­gún ser hu­mano que no sea yo (y a ve­ces ni es­o).

Compu Artesanal

Con­vertí una rasp­ber­ry pi 3 (o 4, aho­ra que sé que an­da) en una com­pu al­l-in-one, con una pan­talla de 8.8 pul­gadas con res­olu­cion 1920x480 (sí, es to­do una com­bi­nación bas­tante ridícu­la)

¿Para qué?

  • Porque quiero apren­der a dis­eñar ob­je­tos fun­cionales.
  • Porque quiero ten­er una com­pu low-end para pro­bar si soft­ware que es­cri­bo fun­ciona con "poco" hard­ware.
  • Porque quiero una com­pu para no mul­ti­taskear. Quiero sen­tarme a es­cribir y es­cribir, o a pro­gra­mar y pro­gra­mar, y no saltar de una cosa a otra.
  • Es el primer es­calón ha­cia hac­erme una note­book casera

¿Que tal viene?

¡Está bási­ca­mente ter­mi­nada! Po­dría de­jar­la co­mo es­tá y de­cir "lis­to", ex­cep­to que al­gu­nas de las partes de la car­caza no son ide­ales, y otras es­tán hechas de dos o tres partes pe­gadas cuan­do de­berían ser una so­la.

¿Fun­ciona? Oh sí.

Features

  • Lin­da pan­talla que les ju­ro es us­able siem­pre y cuan­do la pon­gas jus­to mas al­lá del tecla­do.
  • Un so­lo ca­ble (que se vea des­de el frente) ... in­clu­so tiene una batería, se ban­ca un par de ho­ras des­ench­u­fa­da.
  • Soft­ware con­fig­u­ra­do a me­di­da para el form fac­tor inusu­al.

Lo que me ll­e­va al se­gun­do proyec­to ...

Software configurado para pantallas raras/malas

De­spués de var­ios meses de NO ten­er com­pu en casa me rendí y ha­bil­ité una Thinkpad T430, que es un fier­ro, pero ...

La pan­talla es muy mala. 1384x768. ¡Tiene casi la mis­ma can­ti­dad de pix­els que la pan­talla ridícu­la de mi com­pu arte­sanal!

Así que con DOS com­puta­do­ras con pan­tallas lim­i­tadas de­cidí hac­er al­go al re­spec­to: ele­gir y us­ar soft­ware que no des­perdi­cia tan­to es­pa­cio en pan­talla.

Es­tas son al­gu­nas de las elec­ciones, de­spués de pro­bar lit­eral­mente do­ce­nas de al­ter­na­ti­vas para ca­da cosa.

  • Desk­top: Qtile (con al­gu­na con­fig­u­ración enci­ma)
  • Ter­mi­nal: st (con var­ios parch­es para scroll­back, clip­board y otras cosas)
  • Browser: Qute­brows­er (chrome an­da igual pero des­perdi­cia MUCHA PAN­TALLA)

A su vez tratar de no usar Chrome implica ... donde están mis passwords? Así que estoy migrando a pass ... parece estar andando bien, pero todavía no traté de usarlo en el celular.

A su vez eso me llevó a ...

Software que creo que nadie usa, pero debieran!

Sabés cuan­tas cosas salen si buscás "ter­mi­nal" en Arch Lin­ux? In­cluyen­do los pa­que­tes del AU­R? CIEN­TOS. Y probé una frac­ción grande de el­las.

En par­tic­u­lar me en­con­tré con al­gunos pro­gra­mas que son joy­i­tas que nun­ca había oí­do nom­brar.

  • tab-rs un mul­ti­­plex­er con un so­­lo short­­­cut! de he­­cho ar­mé un set­up bas­­tante ex­­traño usán­­do­­lo pero que me gus­­ta mu­­cho, que merece su propia de­scrip­­ción.

  • slides ... slides! He­­chos con Mark­­down! En una ter­mi­­nal!

  • kiro ... mejor que nano.

Un mouse-joystick

Cuan­do ha­ga mi note­book, voy a nece­si­tar al­go así. Tal vez. Quien sabe.

Y eso me llevó a ...

Programar Raspberry Pi Pico

Mu­cho mas lin­do que pro­gra­mar Ar­duino, y cues­tan lo mis­mo.

Y las posi­bil­i­dades! Es posi­ble hac­er una conex­ión USB a mi mouse-joy­stick y con­fig­u­rar el firmware us­an­do una in­ter­faz de ter­mi­nal!

Quiero un tecla­do que se remapee con una ter­mi­nal se­rie US­B!

No quiero HAC­ER­LO porque no quiero sol­dar to­do eso pero ... y si lo ha­go con un Mod­e­lo M?

Y aparte ...

Y laburo full time. Y leo bas­tante (acá salen los li­bros que voy ter­mi­nan­do)

Así que an­do ocu­pa­do.

Generic run-my-tests-please GitHub Workflow

This post has on­ly one ob­jec­tive. The next per­son who wants to run the tests on his Python project host­ed on GitHub should be able to read it and get his tests run­ning in 15 min­utes or less us­ing GitHub Ac­tion­s.

So, con­cept­s:

  • Github Ac­tion­s: A free (most­ly) con­tin­u­ous in­te­gra­tion thing GitHub gives you so you can run your tests au­to­mat­i­cal­ly, so peo­ple know your project kin­da work­s.
  • Test­s: you should have them.

This as­sumes your project is "mod­ern" in that it us­es Po­et­ry for de­pen­den­cy man­age­ment and pack­ag­ing. Of course maybe it does­n't, but don't wor­ry, that on­ly is im­por­tant for maybe 3 lines of YAM­L.

So, Github Actions runs what's called "workflows". You define these in YAML files in .github/workflows/whatever.yml in your repo.

Here's the orig­i­nal ver­sion of the work­flow we'll be study­ing to­day: test.yml

Don't wor­ry about the project it's in, it re­al­ly does­n't mat­ter.

Now, let's ex­am­ine that file bit by bit with ex­pla­na­tion­s, so you can see if some­thing needs chang­ing for you.

name: CI

on:
  [push, pull_request]

This work­flow is called "CI" and it runs on ev­ery push to any branch.

jobs:
  build:
    strategy:
      matrix:
        python-version: ["3.10"]
    runs-on: ubuntu-latest

Put all the versions of Python you want to test in python-versions. This will run the tests in Ubuntu.

    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
          
      - name: Switch to Current Branch
        run: git checkout ${{ env.BRANCH }}

Check­out this re­po we are test­ing, go to the right branch.

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v1
        with:
          python-version: ${{ matrix.python-version }}

In­stall what­ev­er Python ver­sion we are test­ing.

      - name: Install dependencies
        run: |
          pip install poetry
          poetry install

In­stall what­ev­er you need. Since this project us­es po­et­ry, I in­stall po­et­ry and then use po­et­ry to set­up things. If you are us­ing some­thing else, then change it ac­cord­ing­ly.

      - name: Run unit tests
        run: |
          poetry run pytest

Run the tests in what­ev­er way they need to run. Again, since I am us­ing po­et­ry, this work­s. If you are not, then change this as need­ed.

So, put this file in .github/workflows/test.yml, modify as needed. Commit. Push. Now your tests run on every push.

And that's it. If your project us­es po­et­ry, then this work­flow may work un­changed (ex­cept maybe for Python ver­sion­s?)

Good luck!

Dos trucos con cámaras

Vi al­go en twit­ter, eso me hi­zo googlear, llegué a http­s://ob­spro­jec­t.­com/­fo­rum/thread­s/180-de­gree-live-­fisheye-dis­tor­tion-­cor­rec­tion.100214/ y ... ter­miné ha­cien­do este video, que ex­pli­ca co­mo hac­er dos cosas, una útil, la otra ... no tan­to (aunque es medio pare­ci­do a al­go que ap­ple mostró en WWD­C!)

Sospe­cho que la úni­ca man­era de que ha­ga videos es que sean cosas así, espon­táneas, sin mu­cho laburo atrás porque es­toy ha­cien­do muchas cosas y no ten­go tiem­po.

A database of all chess positions in your own computer

Note: This is based on an old (2018) Quo­ra an­swer.

If I asked you "How much hard drive space would be re­quired for a Data­base rep­re­sent­ing ev­ery pos­si­ble po­si­tion in chess?" what would you an­swer?

Well, most an­swers go like this:

"Claude Shan­non es­ti­mat­ed there are 1043 po­si­tions in chess, which can be stored in ~32 bytes each, so it's some­thing like 1044 bytes, and the ob­serv­able uni­verse has on­ly 1080 atoms so it's some­thing pret­ty large!"

To that I say phooey Shan­non! It takes around 700 bytes if you want the fan­cy ver­sion.

Let's start by defin­ing what the re­quest­ed ar­ti­fact is.

"A data­base rep­re­sent­ing ev­ery pos­si­ble po­si­tion in chess"

So, what is such a database's be­hav­iour? I pro­pose:

  1. It can, if giv­en some sort of in­dex val­ue, re­turn a spe­cif­ic po­si­tion (which will al­ways be the same)
  2. It can it­er­ate over all chess po­si­tion­s.
  3. It should be able to re­turn all po­si­tions match­ing a spe­cif­ic cri­te­ria like 'has a white pawn in D5'

My pro­posed im­ple­men­ta­tion will do the first 2 which I con­sid­er ac­tu­al re­quire­ments, the 3rd be­ing just a "nice to have". While it's not im­pos­si­ble to ad­d, even my will­ing­ness to do stupid things has a lim­it.

So, lim­it­ing my­self to the first two re­quire­ments, if I ful­fill those then it's done, right? Be­cause if the de­liv­er­able is cor­rec­t, the rest is im­ple­men­ta­tion de­tail­s?

Let's im­ple­ment it!

Step 1: notation

Wel­come to Forsyth-Ed­wards no­ta­tion (FEN for short­). It's a won­der­ful thing that pro­vides all the nec­es­sary in­for­ma­tion to restart a game.

I will use a hacked sub­set since all I want is the po­si­tion (not things like "has white cas­tled?" or "who is mov­ing nex­t?") but it's a triv­ial ex­er­cise to ex­pand this data­base to do just that.

So, how does this data­base de­scribe a po­si­tion? A po­si­tion is a list of pieces and their po­si­tions in a 8x8 board.

In the orig­i­nal FEN white pawn is iden­ti­fied as P and black pawn as p. I con­sid­er that an in­sult to the IETF who has adopt­ed UT­F-8 in RFC2777 (and al­so slight­ly racist), there­fore I will use the prop­er glyph­s: ♙ and ♟.

In fac­t, I will use ♙♘♗♖♕♔♟♞♝♜♛♚.

As for po­si­tion­s, since my data­base is small enough that da­ta com­pres­sion is point­less, let's just use a 64-char­ac­ter fixed-­size string where each po­si­tion is ei­ther a piece of a space mean­ing the square is emp­ty.

So, a position is a string of length 64 where these are the only valid values: "♙♘♗♖♕♔♟♞♝♜♛♚ "

Step 2: implementation

It's ob­vi­ous that each po­si­tion is equiv­a­lent to a 64-dig­it num­ber in base 13, which means there are 196 053 476 430 761 073 330 659 760 423 566 015 424 403 280 004 115 787 589 590 963 842 248 960 pos­si­ble po­si­tion­s.

That 64-dig­it num­ber is the in­dex key for each po­si­tion (it's an op­ti­mal key, it can't be made any small­er!)

So here's the data­base core code, of­fered with no com­ments since it's bare­ly 12 lines of code do­ing noth­ing weird:

def get_position(index):
    def digit_to_char(digit):
        return "♙♘♗♖♕♔♟♞♝♜♛♚ "[digit]

    def str_base(number, base=13):
        (d, m) = divmod(number, base)
        if d:
            result = str_base(d, base) + digit_to_char(m)
        else:
            result = digit_to_char(m)
        return result

    position = str_base(index).rjust(64)
    return position

For con­ve­nience, here is a pret­ty print­er for your board­s:

def print_board(position):
    print(" ABCDEFGH ")
    for i in range(8):
        print("%d%s%d" % (i, position[8 * (i) : 8 * (i + 1)], i))
    print(" ABCDEFGH ")

Here you can see it in ac­tion (sad­ly asci­ine­ma butch­ers the align­men­t, it works prop­er­ly in re­al life):

And here is the full source code:

def get_position(index):
    def digit_to_char(digit):
        return "♙♘♗♖♕♔♟♞♝♜♛♚ "[digit]

    def str_base(number, base=13):
        (d, m) = divmod(number, base)
        if d:
            result = str_base(d, base) + digit_to_char(m)
        else:
            result = digit_to_char(m)
        return result

    position = str_base(index).rjust(64)
    return position


def print_board(position):
    print(" ABCDEFGH ")
    for i in range(8):
        print("%d%s%d" % (i, position[8 * (i) : 8 * (i + 1)], i))
    print(" ABCDEFGH ")


if __name__ == "__main__":
    import sys

    print_board(get_position(int(sys.argv[1])))

Please no­tice that this data­base al­so cov­ers all al­ter­na­tive chess vari­ants where ex­tra pieces are giv­en or re­moved as hand­i­cap.

Step 3

There is no step 3.


Contents © 2000-2024 Roberto Alsina