Add 1st lab

pull/1/head
Karim Bogtob 2 years ago
parent 01405ea8a4
commit c5b360ee23

@ -0,0 +1 @@
--require spec_helper --fail-fast --format documentation

@ -0,0 +1,7 @@
On the 9th. William Findley and David Redick--deputed by the Committee of Safety (as it is designated) which met on the 2d. of this month at Parkinson Ferry arrived in Camp with the Resolutions of the said Committee; and to give information of the State of things in the four Western Counties of Pennsylvania to wit--Washington Fayette Westd. & Alligany in order to see if it would prevent the March of the Army into them.
At 10 oclock I had a meeting with these persons in presence of Govr. Howell (of New Jersey) the Secretary of the Treasury, Colo. Hamilton, & Mr. Dandridge: Govr. Mifflin was invited to be present, but excused himself on acct. of business.
I told the Deputies that by one of the Resolutions it would appear that they were empowered to give information of the disposition & of the existing state of matters in the four Counties above men[tioned]; that I was ready to hear & would listen patiently, and with candour to what they had to say.
Mr. Findley began. He confined his information to such parts of the four Counties as he was best acquainted with; referring to Mr. Reddick for a recital of what fell within his knowledge, in the other parts of these Counties.

@ -0,0 +1,18 @@
Maître Corbeau, sur un arbre perché,
Tenait en son bec un fromage.
Maître Renard, par l'odeur alléché,
Lui tint à peu près ce langage :
« Hé ! bonjour, Monsieur du Corbeau.
Que vous êtes joli ! Que vous me semblez beau !
Sans mentir, si votre ramage
Se rapporte à votre plumage,
Vous êtes le Phénix des hôtes de ces bois. »
A ces mots le Corbeau ne se sent pas de joie ;
Et pour montrer sa belle voix,
Il ouvre un large bec, laisse tomber sa proie.
Le Renard s'en saisit, et dit : « Mon bon Monsieur,
Apprenez que tout flatteur
Vit aux dépens de celui qui l'écoute :
Cette leçon vaut bien un fromage, sans doute. »
Le Corbeau, honteux et confus,
Jura, mais un peu tard, qu'on ne l'y prendrait plus.

@ -0,0 +1,46 @@
#!/usr/bin/env ruby
def clean_text(text)
end
def parse(text)
end
def count_occurencies(words)
end
def normalize(occurencies, total_count)
end
def display_top_20(frequencies)
end
# Le code suivant s'execute uniquement lorsque ce fichier est le fichier
# principal en cours d'exécution (et non si il est requis ou chargé
# par un autre fichier)
if $0 == __FILE__
if ARGV.empty?
puts 'usage: frequency.rb <text_file>'
exit 0
end
file_path = ARGV[0]
# Lecture du fichier texte
file_content = File.read(file_path)
# Nettoyage du texte (pour la ponctuation par exemple
cleaned_text = clean_text(file_content)
# Séparation du texte en mots
words = parse(cleaned_text)
# Comptage des occurences des mots
occurencies = count_occurencies(words)
# Calcul des fréquences (normalisation des occurences)
frequencies = normalize(occurencies, words.size)
# Tri et affichage des 20 premiers résultats
display_top_20(frequencies)
end

@ -0,0 +1,46 @@
Hast Du etwas Zeit für mich
Dann singe ich ein Lied für Dich
Von 99 Luftballons
Auf ihrem Weg zum Horizont
Denkst Du vielleicht grad' an mich
Dann singe ich ein Lied für Dich
Von 99 Luftballons
Und dass sowas von sowas kommt
99 Luftballons
Auf ihrem Weg zum Horizont
Hielt man fuer UFOs aus dem All
Darum schickte ein General
'ne Fliegerstaffel hinterher
Alarm zu geben, wenn's so waer
Dabei war'n da am Horizont
Nur 99 Luftballons
99 Duesenflieger
Jeder war ein grosser Krieger
Hielten sich fuer Captain Kirk
Das gab ein grosses Feuerwerk
Die Nachbarn haben nichts gerafft
Und fuehlten sich gleich angemacht
Dabei schoss man am Horizont
Auf 99 Luftballons
99 Kriegsminister
Streichholz und Benzinkanister
Hielten sich fuer schlaue Leute
Witterten schon fette Beute
Riefen: Krieg und wollten Macht
Mann, wer haette das gedacht
Dass es einmal soweit kommt
Wegen 99 Luftballons
99 Jahre Krieg
Liessen keinen Platz fuer Sieger
Kriegsminister gibt's nicht mehr
Und auch keine Duesenflieger
Heute zieh ich meine Runden
Seh' die Welt in Truemmern liegen
Hab' 'nen Luftballon gefunden
Denk' an Dich und lass' ihn fliegen

@ -0,0 +1,85 @@
#!/usr/bin/env ruby
## Consigne : Ecrivez les fonctions décrites en dessous de leurs descriptions.
## Pour executer les tests relatifs au kata, executez 'rspec'
# Signature: add(a, b)
# Retourne l'addition de a et b
def add(a, b)
a + b
end
# Signature: cat(a, b)
# Retourne la concaténation des deux chaines a et b
# Signature: words(s)
# Indice : Regarder la documentation de string
# Retourne les mots de la string s
# Signature: upcase!(s)
# Retourne true mais modifie la string s pour que
# toutes ses lettres soient en majuscules
# Signature: dot(arr)
# Retourne une chaine de caractère avec les éléments du tableau
# séparés par un point milieu · (Attention, ce n'est pas le point de votre clavier!)
# Indice : Regarder la documentation de array
# Exemple : dot(['aut', 'eur', 'trice']) => 'aut·eur·rice'
# Signature: minimum_length_4(s)
# Retourne une chaine de caractère où les mots de moins de 3 caractères
# sont supprimés
# Exemple : minimum_length_4('I do not like potatoes') => 'like potatoes'
# Signature: multiply_array(arr, n)
# Retourne un tableau qui contient tous les nombres de arr multipliés par n
# Exemple : multiply_array([1, 2, 3], 3) => [3, 6, 9]
# Obligation : utiliser l'opérateur #map
# Signature: sum(arr)
# Retourne la somme des nombres du tableau
# Exemple : sum([1, 2, -1, 3]) => 5
# Obligation : utiliser l'opérateur #reduce
# Signature: capitalize_words(s)
# Retourne la string s avec tous les mots en capitalize
# (première lettre en majuscule)
# Exemple : capitalize_words('thanks obama') => 'Thanks Obama'
# Signature: enumeration(n)
# Retourne un tableau qui contient tous les nombres
# de 1 à n
# Indice : Regardez les Range
# Exemple : enumeration(3) => [1, 2, 3]
# Signature: compte_repetitions(arr)
# Retourne le nombre de répétition de chaque mot
# Exemple : compte_repetitions([
# "oui", "bip", "bop", "bip", "blop", "oui",
# "je", "suis", "un", "robot", "oui", "robot"
# ])
# => { "oui" => 2, "bip" => 1, "robot" => 1, "bop" => 0, "blop" => 0, "je" => 0, ... }
# Signature: repetitions(s)
# Retourne le nombre de répétition dans la phrase
# Indice : Un nombre de répétition, c'est pas un nombre d'occurence.
# Indice 2 : Pensez à la casse et par quels caractères splitter`
# Exemple : repetitions("Oui bip bop bip blop. Oui, je suis un robot, oui robot.") => 4
# Signature: dictionnary(s)
# Retourne un hash qui contient les mots pour clés et
# leur définitions comme valeur.
# Exemple: dictionnary('Ours: Mammifère carnivore (ursidé)|Lapin: Mammifère rongeur très prolifique') =>
# { 'Ours' => 'Mammifère carnivore (ursidé)', 'Lapin' => 'Mammifère rongeur très prolifique' }

@ -0,0 +1,157 @@
require 'spec_helper'
describe 'Katas' do
describe '#add' do
it 'adds the two values' do
expect(add(1, 2)).to eq 3
end
it 'adds negatives correctly' do
expect(add(1, -1)).to eq 0
end
end
describe '#cat' do
it 'cats the two values' do
expect(cat('Hello, ', 'world')).to eq 'Hello, world'
end
end
describe '#words' do
it 'returns the words' do
expect(words('Je suis une patate')).to eq ['Je', 'suis', 'une', 'patate']
end
it 'correctly skips spaces the words' do
expect(words(' Vous ne passerez pas ')).to eq [
'Vous',
'ne',
'passerez',
'pas'
]
end
end
describe '#upcase!' do
let(:string) { 'khaaan' }
it 'returns true' do
expect(upcase!(string)).to be true
end
it 'updates the string' do
upcase!(string)
expect(string).to eq 'KHAAAN'
end
end
describe '#dot' do
it 'returns the merged string by a dot' do
expect(dot(['aut', 'eur', 'rice'])).to eq 'aut·eur·rice'
end
end
describe '#minimum_length_4' do
it 'returns the string with only words of min length 4' do
expect(minimum_length_4('I do not like dwarves')).to eq 'like dwarves'
end
it 'can return an empty string if needed' do
expect(minimum_length_4('And my axe')).to eq ''
end
end
describe '#multiply_array' do
it 'multiply the array by the second argument' do
expect(multiply_array([1, 2, 3], 3)).to eq [3, 6, 9]
end
it 'works if the multiplier is negative' do
expect(multiply_array([4, -2, 0], -2)).to eq [-8, 4, 0]
end
end
describe '#sum' do
it 'sums the numbers' do
expect(sum([1, 2, 3])).to eq 6
end
it 'works with an empty array' do
expect(sum([])).to eq 0
end
it 'works with negatives' do
expect(sum([1, 2, -1, 3])).to eq 5
end
end
describe '#capitalize_words' do
it 'returns the string with the words capitalized' do
expect(capitalize_words('Je ne connais pas la ponctuation'))
.to eq 'Je Ne Connais Pas La Ponctuation'
end
end
describe '#enumeration' do
it 'returns the correct enumeration between 1 and n' do
expect(enumeration(3)).to eq [1, 2, 3]
end
it 'works with negatives' do
expect(enumeration(-1)).to eq [-1, 0, 1]
end
end
describe '#compte_repetitions' do
it 'returns the repetitions' do
mots = [
"oui", "bip", "bop", "bip", "blop", "oui",
"je", "suis", "un", "robot", "oui", "robot"
]
expect(compte_repetitions(mots)).to eq({
"bip" => 1,
"blop" => 0,
"bop" => 0,
"je" => 0,
"oui" => 2,
"robot" => 1,
"suis" => 0,
"un" => 0,
})
end
it 'supports an empty word list' do
mots = []
expect(compte_repetitions(mots)).to eq({})
end
end
describe '#repetitions' do
it 'returns the total count of repetitions' do
s = 'Oui bip bop bip blop. Oui, je suis un robot, oui robot.'
expect(repetitions(s)).to eq 4
end
it 'supports a string without repetitions' do
s = 'hello world'
expect(repetitions(s)).to eq 0
end
it 'supports an empty string' do
s = ''
expect(repetitions(s)).to eq 0
end
end
describe '#dictionnary' do
it 'turns a specific string into a dictionnary' do
expect(dictionnary('Ours: Mammifère carnivore (ursidé)|Lapin: Mammifère rongeur très prolifique'))
.to eq({
'Ours' => 'Mammifère carnivore (ursidé)',
'Lapin' => 'Mammifère rongeur très prolifique',
})
end
end
end

@ -0,0 +1,112 @@
require 'spec_helper'
describe 'Frequency' do
describe '#clean_text' do
let(:text) { "some«»text\.not,'\":;![really clean?]" }
it 'cleans the text' do
expect(clean_text(text)).to eq('some text not really clean ')
end
end
describe '#parse' do
let(:text) { 'some text not really clean ' }
it 'splits the text' do
expect(parse(text)).to eq(%w[some text not really clean])
end
end
describe '#count_occurencies' do
let(:words) { %w[some text not really clean and not really original] }
it 'counts occurencies of each word' do
expect(count_occurencies(words)).to eq(
'some' => 1,
'text' => 1,
'not' => 2,
'really' => 2,
'clean' => 1,
'and' => 1,
'original' => 1
)
end
end
describe '#normalize' do
let(:words) { %w[apple banana orange apple banana apple] }
let(:occurencies) do
{
'apple' => 3,
'banana' => 2,
'orange' => 1
}
end
it 'computes frequencies' do
expect(normalize(occurencies, words.size)).to eq(
'apple' => 0.5,
'banana' => 0.333,
'orange' => 0.167
)
end
end
describe '#display_top_20' do
let(:frequencies) do
{
'layout' => 1,
'post' => 1,
'title' => 1,
'tp1' => 2,
'programmation' => 3,
'objet' => 4,
'interpr' => 2,
'entr' => 2,
'mati' => 2,
'categories' => 1,
'ruby' => 32,
'pour' => 21,
'but' => 2,
'vous' => 20,
'faire' => 2,
'pratiquer' => 1,
'les' => 26,
'bases' => 3,
'langage' => 5,
'particulier' => 1,
'prendre' => 2,
'main' => 1,
'que' => 12
}
end
let(:expected_output) do
<<OUTPUT
ruby: 32
les: 26
pour: 21
vous: 20
que: 12
langage: 5
objet: 4
programmation: 3
bases: 3
tp1: 2
interpr: 2
entr: 2
mati: 2
but: 2
faire: 2
prendre: 2
layout: 1
post: 1
title: 1
categories: 1
OUTPUT
end
it 'print the top 20 frequencies' do
expect do
display_top_20(frequencies)
end.to output(expected_output).to_stdout
end
end
end

@ -0,0 +1,8 @@
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
require 'katas'
require 'frequency'
RSpec.configure do |config|
end

File diff suppressed because it is too large Load Diff

@ -0,0 +1,208 @@
---
layout: post
title: "TP1 de programmation objet interprétée - Entrée en matière"
categories: ruby-2a
---
# Entrée en matière
Ce TP a pour but de vous faire pratiquer les bases du langage Ruby, en particulier :
* Prendre en main l'environnement
* Bases de la bibliothèque standard
* Méthodes
* Hash et Map
* Une façon de tester
* Apprendre à mélanger intuition et parcours de la documentation pour découvrir le Ruby que l'on ignore encore
Ruby est un langage 100% objet, tout est objet, même nil (null) ! Mais avant de se lancer dans de la programmation objet, assurons nous d'avoir bien les bases : Amusons avec des scripts classiques, Ruby permet ça aussi !
## Outils
1. Votre éditeur de texte/IDE préféré! Pas de guerre de religion ici! (Liste non exhaustive en bas).
2. *irb* : le débogueur ruby. Idéal pour tester directement des commandes. Peut aussi servir à déboguer.
3. *pry*: irb, en mieux: avec debogueur et couleurs. Installable comme une gemmme (cf. votre cours).
3. *rspec* sera utile pour ce TP. C'est un outil de tests unitaires (ils vous sont fournis cette semaine).
3. *ri*: l'aide locale de ruby, plus rapide que le réseau mais moins jolie (exemple `ri String#scan`)
4. Une ancienne version d'un bon livre sur ruby a été ouverte. Vous la trouverez [](http://ruby-doc.com/docs/ProgrammingRuby/). Elle ne couvre pas tous les ajouts récents mais toute la base du langage est toujours bonne, et bien expliquée.
5. Doc de référence: l'officielle sur [ruby-doc.org](https://ruby-doc.org/core-2.6/). Barre de recherche en haut à droite.
6. Un [cours de programmation](http://evc-cit.info/cit020/beginning-programming/index.html) écrit avec Ruby comme langage support.
Une rapide présentation des IDE ruby est disponible à la fin de ce document... Si vous avez un IDE préféré, il devrait faire l'affaire.
## 1 - Katas marrants
Télécharger les fichiers de ce répertoire (sujet, ainsi que les tests unitaires et fichiers de données nécessaires).
>De la même manière que pour un pratiquant d'art martiaux, les katas sont des exercices que font les développeurs pour améliorer leurs compétences via répétition et entraînement.
Vous devez éditer le fichier `katas.rb` qui contient une liste de fonctions à écrire.
Vous pouvez vérifier vos katas au fur et à mesure de votre dev avec les tests unitaires écrits pour cet usage. Pour cela, ouvrez un terminal, allez dans le dossier de votre projet et tapez simplement `rspec`. Si il n'est pas installé, regardez la section suivante
### Installation de `rspec`
On installe la gemme:
`gem install --user-install rspec`
On cherche le répertoire d'exécutables à ajouter au PATH:
~~~
find ~/.gem -name bin -type d
/home/delobel/.gem/ruby/2.7.0/bin
~~~
On ajoute le chemin au PATH dans le .bashrc (attention, vous n'avez pas forcément la même version de ruby).
`echo 'PATH="$PATH:/home/delobel/.gem/ruby/2.7.0/bin"' >> ~/.bashrc`
On relit le fichier de conf:
`source ~/.bashrc`
## 2 - Calcul de fréquences
### Consignes
Le but de cet application, c'est de prendre un nom de fichier en paramètre et de ressortir les fréquences (nombre d'occurence d'un mot par rapport au nombre de mots total) des 20 mots les plus courants du fichier, en ignorant les mots de moins de 3 caractères et bien sûr les ponctuations.
On veut donc pouvoir la lancer comme suit sur le fichier exemple `french_text.txt`:
```sh
$>ruby frequency.rb french_text.txt
```
Et avoir le résultat suivant :
```
corbeau: 0.029
que: 0.022
vous: 0.022
tes: 0.022
tre: 0.015
bec: 0.015
fromage: 0.015
renard: 0.015
peu: 0.015
monsieur: 0.015
sans: 0.015
votre: 0.015
ces: 0.015
sur: 0.007
arbre: 0.007
perch: 0.007
tenait: 0.007
son: 0.007
par: 0.007
odeur: 0.007
```
Attention, si on ne passe aucun paramètre au programme, un message d'erreur doit s'afficher sur le flux d'erreur (`$stderr`). Exemple :
```
$>ruby frequency.rb
usage: frequency.rb <text_file>
```
### Quelques pistes...
L'utilisation de [Hash](https://docs.ruby-lang.org/en/2.0.0/Hash.html) pour le comptage des mots est particulièrement utile. Surtout si vous l'initialisez avec une valeur par défaut en cas de clef absente...
On ne peut que vous conseiller de séparer l'application en plusieurs responsabilités :
* Lecture du fichier texte
* Nettoyage du texte (pour la ponctuation par exemple)
* Séparation du texte en mots
* Comptage des occurences des mots
* Calcul des fréquences (normalisation des occurences)
* Tri et affichage des 20 premiers résultats
* Programme principal qui associe les différentes responsabilités ensemble
Pour nettoyer le texte, vous pouvez regarder ce que fait `String#gsub(motif, remplacement)`. Un motif peut être une expression rationnelle Ruby (`/^lapino?s/` par exemple).
Cela vous permettra d'écrire plusieurs petites fonctions que vous pourrez tester au fur et à mesure. N'hésitez pas à vous référer aux katas écrits avant.
### Variante (si vous avez été très rapide sur le précédent)
Ajoutez une option -l à votre programme qui permet de calculer la fréquence des différentes lettres du texte.
## 3 - Détection de langues
On vous fournit un fichier JSON `stop_words.json` qui contient les [mots vides](https://fr.wikipedia.org/wiki/Mot_vide) (ou *stopwords*) les plus courants dans les langues les plus courantes.
Les mots sont au format qui suit :
```json
{
"<label de la langue>": [
"<mot vide 1>",
"<mot vide 2>",
...
],
...
}
```
L'idée est de détecter quelle langue est utilisée dans un texte en fonction de ces mots vides. Ainsi, si le texte a la plus grande intersection avec des mots vides de la langue labellisée 'fr' (french), on pourra supposer que le texte est en Français.
L'algorithme est le suivant :
* charger le fichier cible, mettre les mots dans un tableau, supprimer les doublons
* pour chaque langue de la référence
* récupérer la liste des mots vide de la langue courante
* calculer l'intersection entre les mots vides de la langue courante et les mots du texte
* retenir la taille de l'intersection pour la langue courante (un conseil ici, utilisez un hash pour associer langue et taille)
* fin pour
trouver le maximum des intersections calculées
afficher le label du maximum des intersections
On va fournir un texte à analyser via un paramètre de l'application :
```
$>ruby detect_language.rb french_text.txt
```
Et on s'attendra au résultat suivant :
```
Detected language: 'fr'
```
Attention, si on ne passe aucun paramètre au programme, je voudrais un message qui averti l'utilisateur. Exemple :
```
$>ruby detect_language.rb
usage: detect_language.rb <text_file>
```
Testez sur les fichiers `french_text.txt`, `english_text.txt` et `german_text.txt`
### Quelques pistes
On peut vous conseiller de séparer votre code en responsabilités différentes via des méthodes :
|Nom de la méthode|Paramètres|Détail|
|--------|--------|--------|
|load_reference|reference_file_path|Méthode qui renvoie le fichier JSON chargé dans un hash|
|load_text_file|text_file_path|Méthode qui fait le chargement, le nettoyage et la séparation du fichier texte en mots|
|intersection_sizes|reference, text_words| Méthode qui prend la référence et calcul l'intersection entre la liste de mots d'une langue et les mots du texte|
|detect_language|reference, text_words| Méthode qui appelle la méthode précédente et parcours les intersections pour trouver la plus grande et retourne son nom
* Attention lors de la lecture du fichier texte, se référer au deuxième exercice
* Un opérateur magique sur [Array](https://docs.ruby-lang.org/en/2.0.0/Array.html) existe... Il s'écrit comme le 'ET' binaire
* Ne vous laissez pas intimider par le [JSON](http://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html), vous n'avez qu'une méthode statique à appeler sur le module pour parser le document. Cela vous renvoie un Hash qu'il vous suffira de parcourir.
* Pour charger une dépendance de Ruby, on utilise `require 'une_dependance'`. `une_dependance` est un fichier ruby qui peut être dans l'installation standard de Ruby (C'est le cas de JSON), ou une gemme (le système de paquets de ruby que l'on verra par la suite).
## IDE
Les goûts et les couleurs, ça ne se discute pas: il y a rarement d'IDE qui fasse l'unanimité pour un langage ouvert. Voici néanmoins quelques possibilités.
* Vim colore et indente vite.
* Emacs a de bons plugins Ruby, mais nécessite pas mal de configuration pour donner son plein potentiel.
* Geany est un éditeur de texte tout simple mais qui fait bien son boulot.
* Eclipse, Faut être patient au lancement, comme toujours, mais le plugin est correct (Partie de dltk - Dynamic Language ToolKit, qui gère aussi d'autres langages interprétés).
* [Atom](https://atom.io/) est un éditeur libre, développé par github, pas packagé sur debian.
* [Aptana](http://www.aptana.com), un IDE basé sur éclipse. Bonnes capacités aussi pour Ruby On Rails. Disponible aussi sous forme indépendante (un package tout pret).
* Orable a poussé Netbeans à se concentrer sur Java, mais la communauté a repris le développement d'un plugin Ruby & Rails disponible [sur le site officiel](http://plugins.netbeans.org/plugin/38549)
* [RubyMine](https://www.jetbrains.com/ruby/index.html), un IDE dédié à Ruby et Rails, par JetBrains, qui fait aussi IntelliJ, PHPStorm, Clion, etc.
* [Sapphire](http://www.sapphiresteel.com/Products/Ruby-In-Steel/Ruby-In-Steel-Developer-Overview.html), un IDE basé sur visual studio.
* [VS Code](https://code.visualstudio.com/) n'est pas disponible sous Debian, mais un paquet debian est disponible sur le site.
* [VSCodium](https://github.com/VSCodium/vscodium) est une rebuild de VSCode avec uniquement la configuration "comminity" (Sans le branding, la télémétrie, et en licence MIT). Sous ArchLinux, il est en d&pot `aur`, sous debian, vous trouverez les paquets [dans les release](https://github.com/VSCodium/vscodium/releases) du dépot.
Loading…
Cancel
Save