• # un peu de shell

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

    Je ne résiste pas à la réintroduction de split juste pour faire plus aisément la validation du fichier en entrée. Par contre, pas de commande connue qui nous serait utile dans la résolution... Du coup on peut sortir son langage de scripting favori, bien la chose ne soit pas insurmontable malgré l'absence de tableau/liste en POSIX shell (je sais, il y a set qui est très contraignant comparé aux tableaux dans (k|ba|z)sh si on veut rester dans du shell.)

    #!/bin/sh
    # 1ドル: input file
    # 2ドル: split prefix
    for c in 'cut' 'grep' 'tail' 'test'
    do
     if ! command -v "$c" >/dev/null
     then
     echo "Error: command '$c' not found" >&2
     exit 3
     fi
    done
    if test -z "1ドル"
    then
     echo "Please call me with an input file..." >&2
     exit 1
    fi
    _if="1ドル"
    _sp=${2:-x} # Split Prefix
    split -p '^( *[0-9])* *$' -a 1 "$_if" "$_sp" || exit 4
    _bf="Found invalid line, check the file!" # Bad File message
    if test $( ls -1 "$_sp"? | wc -l ) -ne 3
    then
     echo "$_bf a" >&2
     exit 2
    fi
    if grep -Eqsv '^( *\[[A-Z]\])+ *$' "$_sp"a
    then
     echo "$_bf b" >&2
     exit 2
    fi
    if tail -n+2 "$_sp"c | grep -Eqsv '^move [0-9]+ from [1-9] to [1-9]$'
    then
     echo "$_bf c" >&2
     exit 2
    fi
    unset _bf
    _nc=0 # Number of stacks/Columns
    for i in $( cat "$_sp"b )
    do
     _nc=$i
    done
    _cc=2 # Column Counter
    _sl='' # Stacks List
    while test $_nc -ne 0
    do
     _sl="$_sl$( cut -c "$_cc" "$_sp"a | tr -d ' \n' )"
     _nc=$(( _nc - 1 ))
     _cc=$(( _cc + 4 ))
    done
    echo "$_sl" #debug
    # Stack Stard
    # Stack End
    # Cranes Count
    # trashed Word #
    tail -n +2 "${_sp}c" | while read -r _w1 _cc _w2 _ss _w3 _se
    do
     #echo "$_ss→$_se:" #debug
     while test $_cc -ne 0
     do
     _nl='' # New List
     _nc=1 # New Counter
     _cm='' # Crane Moved
     for j in $_sl
     do
     if test $_nc -ne $_ss
     then
     _nl="$_nl$j"
     else
     _cm=$( echo "$j" | cut -c 1 )
     if test ${#j} -ne 1
     then
     _nl="$_nl$( echo "$j" | cut -c 2- )"
     else
     _nl="$_nl -"
     fi
     fi
     _nc=$(( _nc + 1 ))
     done
     _sl=$_nl
     _nl='' # New List
     _nc=1 # New Counter
     for k in $_sl
     do
     if test $_nc -ne $_se
     then
     _nl="$_nl$k"
     else
     if test $k = '-'
     then
     _nl="$_nl$_cm"
     else
     _nl="$_nl$_cm$k"
     fi
     fi
     _nc=$(( _nc + 1 ))
     done
     _sl=$_nl
     _cc=$(( _cc - 1 ))
     done
     echo "$_sl"
    done

    Bien, le tube crée un processus fils avec des variables qui lui sont locales... (i.e. la variable globale $_sl n'est pas modifiée...) Il y a des solutions à cela, mais c'est un plaisir de suivre le travail de la grue avec un truc vite fait d'une part

     NZ DCM P
     DNZ CM P
     - CM ZNDP
     MC - ZNDP
     C M ZNDP

    ...et s'il fallait y passer du temps (plus d'un quart d'heure) et de l'énergie d'autre part, on pouvait directement partir sur un langage de programmation.

    "It is seldom that liberty of any kind is lost all at once." ― David Hume