Voici une implémentation de TapTempo encore plus compacte que l'indigeste one-liner Perl précédent (https://linuxfr.org/users/zerodeux/journaux/taptempo-en-une-ligne), elle vous est offerte par Loïc Cerf qui me l'a soumise et me propose de vous la partager.
J'ai donc l'honneur de vous transmettre sa solution en 97 caractères :
$ awk '{system("date +%s%N")}'|awk '{t[++k]=$0}k>5{r=k-5}k>1{printf"%i",6e10*(k-r-1)/($0-t[r+1])}'
Le comportement est identique à celui de la ligne Perl de Vincent. Elle considère notamment le temps il y a cinq tapes sur la touche Entrée, moins au début… mais je triche en imprimant %i
, le seul tempo (un nombre entier), plutôt que %i bpm
qui mènerait à 101 caractères.
La solution n'est pas particulièrement cryptique. Le premier programme AWK appelle date +%s%N
, comme dans la solution en Bash de superna, à chaque appui sur la touche Entrée, \n
séparant par défaut les "enregistrements" ("record" en anglais) en AWK. Le second programme reçoit donc des nombres de millisecondes depuis l'époque. Il les stocke
dans t[1]
, t[2]
, etc., $0
étant l'enregistrement entier en AWK, qui initialise k
à 0 la première fois que la variable est utilisée (de façon numérique : ici, un incrément). Au premier enregistrement, rien n'est fait : les tests k>5
et k>1
échouent. Du second au cinquième, seul le test k>1
passe et l'entier imprimé est le tempo calculé en considérant le dernier temps ($0
), le premier (t[r+1]
est t[1]
puisque r
vaut 0), le nombre d'intervalle (k-1
) et le fait que le temps est en millisecondes plutôt qu'en minutes (facteur 6e10
). À partir du sixième enregistrement
(k>5
), r
est défini comme étant k-5
de sorte que le tempo est calculé en considérant le dernier temps ($0
), le temps au k-5+1 = k-4
ème enregistrement et donc k-r-1 = k-(k-5)-1 = 4
intervalles.
J'avais au départ une solution similaire en 103 caractères (107 en écrivant " bpm"). J'ai proposé un défi TapTempo après avoir enseigné AWK ( https://dcc.ufmg.br/~lcerf/slides/mda6.pdf ) à mes étudiants (je suis professeur à l'Université Fédérale du Minas Gerais, au Brésil) : réaliser la même chose en moins de caractères. Une étudiante a économisé trois caractères. J'ai ensuite encore gagné trois caractères.
Si l'un de vous deux veut participer au renouveau d'intérêt pour TapTempo, je n'ai rien contre un journal qui présente cette solution en moins de 100 caractères. Je suis en fait curieux de découvrir si quelqu'un trouvera une solution encore plus brève.
Loïc.
# awk '{system("date +%s%N")}' c'est long
Posté par KiKouN . Évalué à 10.
il est possible de remplacer le premier awk par ts :
Ce qui donne :ts "%s"
Ça fait gagner 20 caractères mais c'est plus du pur awk. En même, date est utilisé, donc c'est déjà plus trop du pur awk.ts "%s"|awk '{t[++k]=$0}k>5{r=k-5}k>1{printf"%i",6e10*(k-r-1)/($0-t[r+1])}'
[^] # Re: awk '{system("date +%s%N")}' c'est long
Posté par KiKouN . Évalué à 2.
Note: les guillemets pour l'expression de la date de ts ne sont pas utile.
[^] # Re: awk '{system("date +%s%N")}' c'est long
Posté par zerodeux (site web personnel) . Évalué à 1.
Je transmet une réponse de Loïc, auteur de la solution Awk originelle :
ts "%s" donne une seconde de résolution. Cela ne suffit pas.
Heureusement, ts accepte aussi "%.s" pour une partie fractionnaire (un caractère de plus). Et pas besoin des guillemets : deux caractères de moins. Aussi, avec des secondes plutôt que des nanosecondes, le facteur 6e10 dans le programme AWK devient 60 : encore deux caractères de moins.
La solution prend alors 72 caractères :
$ ts %.s|awk '{t[++k]=$0}k>5{r=k-5}k>1{printf"%i",60*(k-r-1)/($0-t[r+1])}'
Si 100 caractères est la limite, on peut se permettre d'ajouter la remise à zéro après 5 secondes sans taper, comme dans le projet initial de mzf, et utiliser son format de sortie ("Tempo : %i bpm") :
100 caractères. Pile poil. Quelqu'un trouvera-t-il mieux ?ts %.s|awk '$0-t[k]>5{k=r=0}{t[++k]=$0}k>5{r=k-5}k>1{printf"Tempo : %i bpm",60*(k-r-1)/($0-t[r+1])}'
# ne marche pas avec mawk
Posté par freem . Évalué à 2.
Ne marche pas avec
mawk
pour le coup. Je pense que c'est lié à l'utilisation de comparaison pour les patterns, alors que ça devrais puisque le standard (POSIX-10031-2017) dit:plus loin:
Du coup, je me demande si ça ne serait pas un bug de mawk? Ça y ressemble en tout cas beaucoup?
Peut-être spécifique à debian?
Pour info:
```sh
% mawk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
compiled limits:
max NF 32767
sprintf buffer 2040
```
[^] # Re: ne marche pas avec mawk
Posté par anaseto . Évalué à 2.
Ça ne marche pas avec le awk original non plus (celui installé de base sur OpenBSD). J'obtiens que des lignes vides et, parfois, une division par zéro… je sais pas trop pourquoi encore.
[^] # Re: ne marche pas avec mawk
Posté par anaseto . Évalué à 2.
Ah oui, en fait, déjà %N n'existe pas dans le date de OpenBSD, donc c'était mal parti.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.