🚲 Tanguy Ortolo a écrit 12091 commentaires

  • [^] # Re: En Python, modĂ©lisĂ©

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 9. Évalué à 4. Dernière modification le 09 décembre 2022 à 18:05.

    Tu peux te passer de la position initiale dans l'ensemble des positions visitées : après le premier mouvement, la queue de la corde y sera toujours.

  • # Coin coin

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 9. Évalué à 4.

    Le problème parle de corde à nœuds, mais m'évoquerait plutôt une canne et ses canetons, pas vous ?

  • [^] # Re: En Python, modĂ©lisĂ©

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 9. Évalué à 3. Dernière modification le 09 décembre 2022 à 16:58.

    Bon, en fait, pas besoin d'énumérer de façon aussi laborieuse bien sûr :

    from __future__ import annotations
    
    from enum import Enum
    from typing import Iterable, Iterator, Set, Tuple
    
    
    Coords = Tuple[int, int]
    
    
    class Direction(Enum):
        O  = ( 0,  0)
        U  = ( 0,  1)
        D  = ( 0, -1)
        L  = (-1,  0)
        R  = ( 1,  0)
    
        def __init__(self, dx, dy):
            self.dx = dx
            self.dy = dy
    
    
    class Knot:
        def __init__(self, x: int, y: int):
            self.x = x
            self.y = y
    
        @property
        def coords(self) -> Coords:
            return (self.x, self.y)
    
        def move(self, direction: Direction) -> None:
            self.x += direction.dx
            self.y += direction.dy
    
        def dist(self, other: Knot) -> int:
            return max(abs(self.x - other.x), abs(self.y - other.y))
    
        def follow(self, other: Knot) -> None:
            if self.dist(other) <= 1:
                return
            if self.x < other.x:
                self.x += 1
            if self.x > other.x:
                self.x -= 1
            if self.y < other.y:
                self.y += 1
            if self.y > other.y:
                self.y -= 1
    
    
    class Rope:
        def __init__(self, n_knots: int) -> None:
            self.knots = [Knot(0, 0) for _ in range(n_knots)]
    
        @property
        def head(self) -> Knot:
            return self.knots[0]
    
        @property
        def tail(self) -> Knot:
            return self.knots[-1]
    
        def move(self, direction: Direction) -> None:
            self.head.move(direction)
            for i in range(1, len(self.knots)):
                leader = self.knots[i - 1]
                follower = self.knots[i]
                follower.follow(leader)
    
    
    def import_lines(lines: Iterable[str]) -> Iterator[Direction]:
        for line in lines:
            word1, word2 = line.split()
            direction = Direction[word1]
            repeat = int(word2)
            for _ in range(repeat):
                yield direction
    
    
    def solve_both(lines: Iterable[str]) -> Tuple[int, int]:
        """Solve both parts of today's puzzle"""
        rope = Rope(10)
        visited1 = set()  # type: Set[Coords]
        visited2 = set()  # type: Set[Coords]
        for direction in import_lines(lines):
            rope.move(direction)
            visited1.add(rope.knots[1].coords)
            visited2.add(rope.tail.coords)
    
        return len(visited1), len(visited2)
  • [^] # Re: En Python, modĂ©lisĂ©

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 9. Évalué à 3.

    Ce serait sans doute plus joli avec des coordonnées indexées (une liste de coordonnées en somme) plutôt que nommées.

    Mais ce n'est de toute façon pas très compréhensible, de cette façon-là.

  • # En Python, modĂ©lisĂ©

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 9. Évalué à 4.

    #! /usr/bin/python3
    
    # Advent of Code 2022, day 9
    
    from __future__ import annotations
    
    from enum import Enum
    from typing import Iterable, Iterator, Set, Tuple
    
    
    Coords = Tuple[int, int]
    
    
    class Direction(Enum):
        O  = ( 0,  0)
        U  = ( 0,  1)
        D  = ( 0, -1)
        L  = (-1,  0)
        R  = ( 1,  0)
        UL = (-1,  1)
        UR = ( 1,  1)
        DL = (-1, -1)
        DR = ( 1, -1)
    
        def __init__(self, dx, dy):
            self.dx = dx
            self.dy = dy
    
    
    class Knot:
        def __init__(self, x: int, y: int):
            self.x = x
            self.y = y
    
        @property
        def coords(self) -> Coords:
            return (self.x, self.y)
    
        def move(self, direction: Direction) -> None:
            self.x += direction.dx
            self.y += direction.dy
    
        def dist(self, other: Knot) -> int:
            """"Chebyshev distance! (Not really used in my code, actually)"""
            return max(abs(self.x - other.x), abs(self.y - other.y))
    
        def direction_to(self, other: Knot) -> Direction:
            dx = other.x - self.x
            dy = other.y - self.y
            if dx < -1:
                if dy < 0:
                    return Direction.DL
                if dy == 0:
                    return Direction.L
                if dy > 0:
                    return Direction.UL
            if dx == -1:
                if dy < -1:
                    return Direction.DL
                if -1 <= dy <= 1:
                    return Direction.O
                if dy > 1:
                    return Direction.UL
            if dx == 0:
                if dy < -1:
                    return Direction.D
                if -1 <= dy <= 1:
                    return Direction.O
                if dy > 1:
                    return Direction.U
            if dx == 1:
                if dy < -1:
                    return Direction.DR
                if -1 <= dy <= 1:
                    return Direction.O
                if dy > 1:
                    return Direction.UR
            if dx > 1:
                if dy < 0:
                    return Direction.DR
                if dy == 0:
                    return Direction.R
                if dy > 0:
                    return Direction.UR
            assert False  # cannot happen, all cases were covered
    
        def follow(self, other: Knot) -> None:
            self.move(self.direction_to(other))
    
    
    class Rope:
        def __init__(self, n_knots: int) -> None:
            self.knots = [Knot(0, 0) for _ in range(n_knots)]
    
        @property
        def head(self) -> Knot:
            return self.knots[0]
    
        @property
        def tail(self) -> Knot:
            return self.knots[-1]
    
        def move(self, direction: Direction) -> None:
            self.head.move(direction)
            for i in range(1, len(self.knots)):
                leader = self.knots[i - 1]
                follower = self.knots[i]
                follower.follow(leader)
    
    
    def import_lines(lines: Iterable[str]) -> Iterator[Direction]:
        for line in lines:
            word1, word2 = line.split()
            direction = Direction[word1]
            repeat = int(word2)
            for _ in range(repeat):
                yield direction
    
    
    def solve_both(lines: Iterable[str]) -> Tuple[int, int]:
        """Solve both parts of today's puzzle"""
        rope = Rope(10)
        visited1 = set()  # type: Set[Coords]
        visited2 = set()  # type: Set[Coords]
        for direction in import_lines(lines):
            rope.move(direction)
            visited1.add(rope.knots[1].coords)
            visited2.add(rope.tail.coords)
    
        return len(visited1), len(visited2)

    J'aurais bien aimé éviter d'énumérer tous les cas de mouvement de suivi, mais je n'ai rien trouvé d'astucieux pour éviter cela.

    J'espère que dans vos solutions perso, vous aurez pensé à utiliser, en arrivant à la deuxième partie, à utiliser une seule corde pour simuler les deux…

  • [^] # Re: python procĂ©dural, moche mais efficace

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 8. Évalué à 4.

    Une petite optimisation pour la première partie : si on arrive à une hauteur de 9, pas la peine de regarder plus loin, aucun arbre ne sera plus haut que ça.

    Mais bon, la seconde partie est bien plus coûteuse en temps de toute façon.

  • # Procrastination

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 8. Évalué à 3.

    Alors qu'on a enfin quitté le camp pour aller chercher des caramboles, je ne peux m'empêcher que ça procrastine encore :

    – Voilà, le verger c'est par là…
    – Oh, regardez, la forêt que nous avons planté il y a quelques années, on pourrait y construire une cabane !
    – Oui, super, ça nous changera les idées. Lutin drone-opérateur, tu nous cartographie ça ?
    – Patron, venez nous donner un coup de main pour calculer le meilleur emplacement pour notre cabane au lieu d'essayer de régler votre communicateur. On vous l'a déjà dit, il est défectueux, et vous aurez tout le temps pour le réparer plus tard. On a plus important à faire là !
    – Et les fruits pour les rennes alors ?
    – Les quoi ? Ah, ça… On n'y est pas encore, soyez patient. Vous êtes pressé, vous avez un rendez-vous qui approche ou quoi ?

  • # Python avec Numpy

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 8. Évalué à 4.

    Bon, j'ai sorti Numpy du coup. C'est modélisé, et assez long en fait.

    # Advent of Code 2022, day 8
    
    from __future__ import annotations
    
    from math import prod
    from typing import Iterable, Iterator, Set, Tuple, Type
    
    import numpy as np
    
    
    Coords = Tuple[int, int]
    
    
    class Grid:
        def __init__(self, matrix: np.ndarray) -> None:
            self.matrix = matrix
            self.ly = matrix.shape[0]
            self.lx = matrix.shape[1]
    
        def __scans(self) -> Iterator[Iterator[Iterator[Coords]]]:
            yield (((y, x) for x in range(self.lx)) for y in range(self.ly))
            yield (((y, x) for x in range(self.lx - 1, -1, -1))
                   for y in range(self.ly))
            yield (((y, x) for y in range(self.ly)) for x in range(self.lx))
            yield (((y, x) for y in range(self.ly - 1, -1, -1))
                   for x in range(self.lx))
    
        def visible_from_outside(self) -> Set[Coords]:
            visible_trees = set()  # type: Set[Coords]
            for scan in self.__scans():
                for line in scan:
                    max_height = -1
                    for coords in line:
                        cur_height = self.matrix[coords]
                        if cur_height > max_height:
                            visible_trees.add(coords)
                            max_height = cur_height
            return visible_trees
    
        def __viewing_distance(self, orig: Coords, line: Iterator[Coords]) -> int:
            height = self.matrix[orig]
            d = 0
            for coords in line:
                d += 1
                if self.matrix[coords] >= height:
                    return d
            return d
    
        def __lines_of_sight(self, coords: Coords):
            y, x = coords
            yield ((y, x_) for x_ in range(x + 1, self.lx))
            yield ((y, x_) for x_ in range(x - 1, -1, -1))
            yield ((y_, x) for y_ in range(y + 1, self.ly))
            yield ((y_, x) for y_ in range(y - 1, -1, -1))
    
        def scenic_score(self, coords: Coords):
            return prod(self.__viewing_distance(coords, line)
                        for line in self.__lines_of_sight(coords))
    
        @classmethod
        def import_lines(class_: Type[Grid], lines: Iterable[str]) -> Grid:
            matrix = np.genfromtxt(lines, delimiter=1, autostrip=True, dtype=int)
            return class_(matrix)
    
    
    def solve_both(lines: Iterable[str]) -> Tuple[int, int]:
        """Solve both parts of today's puzzle"""
        # Import
        grid = Grid.import_lines(lines)
        # Part 1
        visible = len(grid.visible_from_outside())
        # Part 2
        max_score = max(grid.scenic_score(coords) for coords
                        in np.ndindex(grid.matrix.shape))
        return visible, max_score
  • [^] # Re: HS

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 3.

    En fait, en matière d'assurance, et d'assurance de quoi que ce soit en fait, je pense qu'il serait possible d'autoriser la modulation de cotisation en fonction de n'importe quoi qui relève du choix de l'assuré, à condition que le traitement des informations correspondantes soit légal évidemment. L'âge et l'état de santé par exemple, ne relèvent pas du tout du choix.

    Mais le tabagisme, le nombre d'infractions routières ou encore le nombre de soirées passées au cinéma chaque mois, relèvent du choix. Le dernier exemple n'a rien de pertinent, mais inutile d'interdire la modulation d'un tarif en fonction de cela : lorsque ce n'est pas pertinent, c'est inintéressant à appliquer, parce que cela ne correspond pas au risque assuré, que ça attirera juste une clientèle spécifique et que la remise correspondante s'avérera coûteuse pour l'assureur.

  • [^] # Re: HS

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 4.

    Du moment où ils ont la permission de ne moins payer la cotisation retraite (espérance de vie moindre) et de ne pas payer les taxes déjà actuelles sur les cigarettes (pas payer 2x la même chose), ok, ils vont applaudir les fumeurs de ne payer que ce qu'ils coûtent comme tu le souhaites!

    Il y a plusieurs choses lĂ -dedans. Les taxes ont deux rĂ´les :

    • financer le coĂ»t des soins pour les fumeurs : avec une possibilitĂ© de tarifier diffĂ©remment l'assurance santĂ©, ça devrait effectivement disparaĂ®tre ;
    • financer le coĂ»t des soins aux victimes de tabagisme passif : ça doit rester ;
    • dissuader le tabagisme, notamment Ă  cause des nuisances qu'il reprĂ©sente : ça doit rester aussi.

    et les accidentés vélotafs sont actuellement acceptés sans surcoût mais si tu veux des différences je militerai pour que toi tu payes un max suivant l'usage vélotaf que je jugerai pour toi comme plus dangereux que train, X ou Y tout aussi subjectif que toi

    Ça n'a rien de subjectif, ça a été étudié, et surprise, le vélotaf est dangereux, mais ne pas en faire l'est encore plus. Les assureurs sont d'accord, ce qui est l'essentiel, dans cette discussion.

    https://www.matmut.fr/assurance/nvei/conseils/velo-travail-bonnes-raisons
    https://www.ors-idf.org/nos-travaux/publications/les-benefices-et-les-risques-de-la-pratique-du-velo/

    C'est surtout démagogique pour te croire mieux que d'autres, pas factuel.

    Non, pas du tout, c'est une question de justice. C'est comme les assurances emprunteur par exemple : non fumeur, ça coûte moins cher que fumeur, c'est juste normal. Et ça ne pénalise que ceux qui le veulent bien.

    PS : perso si on va dans cette direction je serai plus sur faire sur-cotiser les non-vaccinés de tout poil (vous avez fait vos rappels adultes?) car un choix très individuel et calcul de risque qui fait que ça coûte plus (et c'est ce qu'on fait des assurances US) sans apporter assez ailleurs (risque de survivre après réa, pas d'autres taxes déjà en cours), mais la ça risque de troller :).

    Pas forcément moduler ainsi les cotisations, simplement permettre de le faire. Pour la vaccination, c'est pertinent aussi en effet. Beaucoup plus pertinent qu'une obligation plus ou moins forte en fait, puisqu'il s'agit de répercuter directement le coût statistique d'un choix personnel sur le budget de celui qui le fait. Pour responsabiliser les gens, on ne peut pas faire mieux je pense. Tant qu'il s'agit simplement de critères qui relèvent du choix des gens, aucun problème.

  • # Procrastination

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 7. Évalué à 4.

    On dirait que le Père Noël, ou les lutins, ou les deux, ne sont pas si motivés que ça pour aller effectivement courir la jungle pour récolter des caramboles. Ça traîne à faire des inventaires, à monter le camp, à nettoyer le camp, à décharger le bateau, à réorganiser le matériel déchargé, à bidouiller des communicateurs, à mettre à jour ces communicateurs…

    Ça fait six jours qu'on a débarqué, et n'a pas encore bougé du camp ! Vivement que les lutins nous fournissent une carte pour aller quelque part.

  • [^] # Re: C'est parti !

    Posté par  (site web personnel) . En réponse au journal Calendrier de l'Avent du code. Évalué à 4.

    Sujets plus simple, je suis d'accord… pour le moment. Ça pourrait se corser d'un coup !

  • [^] # Re: Vivement , le 1

    Posté par  (site web personnel) . En réponse au journal Calendrier de l'Avent du code. Évalué à 6.

    Pareil pour moi, surtout que j'aime faire du beau code, et que ça ne va pas bien avec l'idée de faire la course.

    Mais pas d'inquiétude, on devrait finir par avoir des problèmes qu'on sera déjà content de parvenir à résoudre tout court, au bout d'un moment. :-)

  • [^] # Re: un bout de AWK

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 7. Évalué à 3. Dernière modification le 07 décembre 2022 à 15:19.

    En fait vu la structure de l'input où il n'y a que de cd child et cd .. # parent, c'est nécessairement un parcours d'arbre en profondeur d'abord.

    $ cd /
    $ ls
    4212 aoc.py
    dir 2021
    dir 2022
    $ cd 2021
    $ ls
    dir 12
    $ cd ..
    $ cd 2022
    $ ls
    dir 12
    $ cd ..
    $ cd 2021
    $ cd 12
    $ ls
    42 01.py
    12 02.py
    51 03.py
    $ cd ..
    $ cd ..
    $ cd 2022
    $ cd 12
    $ ls
    12 01.py
    51 02.py
    42 03.py
    

    C'est idiot, on est d'accord. Mais ce n'est pas un parcours en profondeur d'abord.

  • [^] # Re: En Python bref

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 2. Évalué à 3. Dernière modification le 07 décembre 2022 à 14:52.

    Waouh. C'est pour le moins original ça.

        def __invert__(self):
            """~chifumi returns value in [1, 2, 3]"""
            return (self.chifumi % 3) or 3

    Si je comprends bien, ça fait de ~ une opération pour récupérer la valeur normalisée. Bien joué le (valeur % 3) or 3, c'est bien plus lisible que (valeur - 1) % 3 + 1.

        def __pos__(self):
            return ((self.chifumi + 1) % 3) or 3
    
        def __neg__(self):
            return ((self.chifumi - 1) % 3) or 3

    La valeur qui me vainc et la valeur que je vaincs, si je ne m'abuse.

        def __lt__(self, other):
            return +self == ~other
    
        def __gt__(self, other):
            return -self == ~other

    Je suis plus inférieur à un autre si la valeur qui me vainc est la même que la valeur normalisée de l'autre. Et mutatis mutandis pour la supériorité. Tu aurais pu utiliser functool.total_ordering().

    Ensuite, le reste est assez simple à comprendre, une fois ces bases posées. La réutilisation des opérateurs est… intéressante. Je ne peux pas dire que je suis fan, c'est un peu bizarre à lire quand même.

    values = dict(
        A=chifumi(1),
        B=chifumi(2),
        C=chifumi(3),
        X=chifumi(1),
        Y=chifumi(2),
        Z=chifumi(3),
    )

    Tiens, j'ignorais la possibilité d'instancier un dictionnaire avec des mots-clefs. C'est amusant, ça aussi.

  • [^] # Re: Mutuelle

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 1.

    Le jour où j'aurai le choix de mon prestataire de sécu (comme par exemple en Allemagne, qui pour une fois fait les choses largement plus intelligemment, tu as le choix de l'entité qui fait en même temps base obligatoire et complémentaire optionnelle avec les mêmes règles pour le paiement; qu'on se rassure, ils ont merdé ailleurs en permettant du "privé" qui ne respectent pas ces règles. Et sur quoi se battent les différentes entités si elles ne peuvent jouer sur le prix? Sur la qualité de prestation!), je changerai et ferai la différence entre la sécu couverture obligatoire et la sécu entité à laquelle je me suis inscrite.

    Je suis tout aussi critique que toi sur le fait de ne pas avoir le choix. Je rêve d'avoir le choix entre la CPAM et d'autres assureurs. Et je ne vois pas le problème que ça poserait, du moment que la couverture est règlementée (obligation de couvrir au moins ceci et cela à tel taux ou plafond de remboursement), ainsi et que l'éligibilité et la tarification différenciée : concrètement, interdiction de refuser les vieux et les cancéreux et de leur faire payer plus cher parce que ce n'est pas un choix, mais permission de faire payer plus cher les fumeurs, et moins cher les gens qui font trois heures d'exercice par semaine, vélotaf inclus.

  • [^] # Re: En Python

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 7. Évalué à 3.

    Pas en ReiserFS, le système de fichier qui tue le gaspillage d'espace de stockage.

  • [^] # Re: En Python

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 7. Évalué à 5.

    Et surtout pas de yield dans la fonction recursive qui aplatit les repertoires (je copie les references dans une nouvelle list). J'avoue que ta solution est plus elegante, et c'est marrant que tu fasses du code presque prod ready (mypy…).

    Je profite en fait de l'AoC pour découvrir les fonctionnalités de typage de Python. Une fois passé l'apprentissage, qui n'est vraiment pas horrible, ça ne fait pas perdre du temps, au contraire, ça permet de détecter certaines erreurs de façon bien plus rapide et de mieux identifier d'où elles viennent.

  • [^] # Re: un bout de AWK

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 7. Évalué à 3.

    Comme le FS est parcourus "en profondeur d'abord" et dans l'ordre, pas besoin d'une structure de données trop compliquée type arbre, une simple liste suffit.

    Bien joué, je n'avais pas remarqué cela. Ceci dit, je n'aime pas trop me baser sur des suppositions qui ne sont absolument pas garanties par l'énoncé.

  • # En Python

    Posté par  (site web personnel) . En réponse au message Avent du Code, jour 7. Évalué à 5.

    Ça commence à devenir un tout petit peu sérieux. Aucune vraie difficulté à comprendre ou à implémenter le problème, mais on commence à sortir des trucs un peu récursifs.

    En bon unixien, je considère bien sûr qu'un répertoire est un type particulier de fichier, qu'il contient toujours une vraie entrée .., et que le nom d'un fichier n'est pas une propriété intrinsèque mais simplement un nom qu'il porte dans une entrée de répertoire.

    # Advent of Code 2022, day 7
    
    from __future__ import annotations
    
    import re
    
    from enum import Enum
    from typing import Dict, Iterable, Iterator, Optional, Tuple
    
    
    class File:
        def __init__(self, size: int):
            self.size = size
    
    
    class RegularFile(File):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
    
    class Directory(File):
        def __init__(self, parent: Optional[Directory] = None):
            if parent is None:
                # root directory
                parent = self
            self.files = {'..': parent}  # type: Dict[str, File]
            self._size = None            # type: Optional[int]
    
        @property
        # https://github.com/python/mypy/issues/4125
        def size(self) -> int:  # type: ignore
            if self._size is None:
                self._size = sum(f.size for name, f in self.files.items()
                                 if name != '..')
            # mypy does not realize self._size can no longer be None
            return self._size  # type: ignore
    
        def add(self, name, f: File) -> None:
            self.files[name] = f
    
        def dirs(self) -> Iterator[Directory]:
            yield self
            for name, f in self.files.items():
                if isinstance(f, Directory) and name != '..':
                    yield from f.dirs()
    
    
    class State:
        re_cd = re.compile(r'^\$ cd (.*)\n?$')
        re_ls = re.compile(r'^\$ ls\n?$')
        re_reg = re.compile(r'^(\d+) (.*)\n?$')  # regular file
        re_dir = re.compile(r'^dir (.*)\n?$')
    
        def __init__(self, root: Directory):
            self.root = root
            self.cwd = root
            self.in_ls = False
    
        def cd(self, name: str) -> None:
            # Only 'cd /' or 'cd subdir'!
            if name == '/':
                self.cwd = self.root
            else:
                target = self.cwd.files[name]
                if isinstance(target, Directory):
                    self.cwd = target
                else:
                    raise ValueError('cannot cd to a regular file')
    
        def input(self, line: str) -> None:
            if (m := self.re_cd.match(line)) is not None:
                self.in_ls = False
                self.cd(m.group(1))
            elif (m := self.re_ls.match(line)) is not None:
                self.in_ls = True
            elif self.in_ls and (m := self.re_reg.match(line)) is not None:
                size = int(m.group(1))
                name = m.group(2)
                self.cwd.add(name, RegularFile(size))
            elif self.in_ls and (m := self.re_dir.match(line)) is not None:
                name = m.group(1)
                self.cwd.add(name, Directory(parent=self.cwd))
            else:
                raise ValueError("unexpected line '{}'".format(line.rstrip()))
    
    
    def import_tree(lines: Iterable[str]) -> Directory:
        root = Directory()
        state = State(root)
        for line in lines:
            state.input(line)
        return root
    
    
    def solve_both(lines: Iterable[str]) -> Tuple[int, int]:
        """Solve both parts of today's puzzle"""
        root = import_tree(lines)
        result1 = sum(d.size for d in root.dirs() if d.size <= 100000)
    
        total = 70000000   # total storage space
        needed = 30000000  # storage space needed for system update
        used = root.size   # used storage space
        available = total - used      # currently available storage space
        to_free   = needed - available  # storage space to free
        result2 = min(d.size for d in root.dirs() if d.size >= to_free)
    
        return result1, result2
  • [^] # Re: Mutuelle

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 8.

    Exact, mais sans intérêt. Ce qui est intéressant, c'est de comprendre de quoi on parle : un système régi par la loi et des assurances qui en sont l'implémentation, sous la forme d'une sorte d'oligopole légal assez unique en son genre.

    L'utilisation de termes aussi vague que « la sécu » me semble donner l'impression qu'il s'agirait d'une administration d'État, avec laquelle les citoyens auraient la même relation qu'avec le fisc ou la préfecture du coin. Ça en fait un organisme puissant et distant de ses clients.

    Alors que c'est bien plus clair en parlant simplement d'assurance : il n'est pas question de citoyens mais d'adhérents (voire de clients), et la relation est la même que celle qu'on peut avoir avec son assureur habitation ou automobile (d'ailleurs c'est obligatoire aussi, seulement pour celles-là, on a le choix de l'assureur).

  • [^] # Re: Mutuelle imposĂ©e

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 7.

    Sauf que ce n'est pas du tout offert, c'est payé par les cotisation des employés. À moins qu'ils n'y ait des preuves, ou au moins de soupçons que l'employeur paie discrètement un supplément de cotisation sans le déclarer justement.

    Sinon, ça ce compte-là, on pourrait aussi dire que le remboursement de l’ostéopathie est « offerte » puisqu'il n'y a pas de surcoût. C'est idiot, ça fait partie du contrat, en échange de la cotisation.

  • [^] # Re: Mutuelle imposĂ©e

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 6.

    Avantage en nature non déclaré ‽ Avantage en nature, d'accord, mais non déclaré, c'est n'importe quoi, la cotisation apparaît sur la fiche de paie !

    Je comprendrais que des célibataires se sentent lésés par le fait de cotiser ce qu'il faut pour couvrir les conjoints des autres, mais ce n'est pas du tout un problème de déclaration de l'avantage en question.

  • [^] # Re: Mutuelle imposĂ©e

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 8.

    j'ai le cas: mutuelle imposée par la boite de mon épouse. On a voulu stopper ça et… Cest possible uniquement si la seconde mutuelle est dite familiale, donc couvre toute la famille par défaut sans surcout.

    Pas tout ça fait, c'est pire que ça. L'assurance complémentaire peut exigée une preuve que tu es couvert obligatoirement par celle de ton conjoint. Si c'est facultatif, même sans surcoût, ils peuvent refuser.

    Ça fait partie des idées de lois dont je dois parler à mon député. Dans le même sens que la liberté de choisir son assurance emprunteur, ce serait bien d'avoir la liberté de choisir son assurance complémentaire santé. L'obligation pour l'employeur d'en fournir une pourrait être maintenue, avec la possibilité de cesser d'y cotiser sur preuve qu'on a déjà une complémentaire santé, sans plus de contrainte.

  • [^] # Re: Mutuelle imposĂ©e

    Posté par  (site web personnel) . En réponse au journal Mutuelle et mot de passe. Évalué à 6. Dernière modification le 06 décembre 2022 à 16:37.

    Oui. On a le droit de ne pas adhérer à la mutuelle assurance complémentaire santé (cf. infra) obligatoirement proposée par son employeur, à condition de prouver qu'on est obligatoirement couvert par celle de son conjoint.

    C'est très subtil, parce que si par exemple, l'assurance de ton conjoint te couvre de façon optionnelle, mais sans surcoût, ça ne te donne pas le droit de ne pas adhérer à la tienne.

    (Bon, après, la seule différence entre un certificat comme quoi on est couvert sans surcoût, et un certificat comme quoi on est obligatoirement couvert sans surcoût, c'est un seul mot, donc rien d'insurmontable, si vous voyez ce que je veux dire. o:-) )