そろばんの計算の仕組みをシミュレートして足し算をするプログラムを書いてみました。
JavaScriptで書きました。
コードをページの下部に記載します。自前の特殊文字置換ツールを利用しました。
答えに出てくる記号の羅列は、計算の操作をした結果で出るそろばんの形を表しています。
行の上から下の桁になります
*はそろばんの珠、ーは珠のないところ、|はそろばんの5の位と1の位を分ける線です。
10進数を基に計算していますので、小数でも誤差は出ないです。
今のところ小数には対応していませんが…
また引き算や、掛け算割り算にも対応できるはずです。
現在最大5桁の自然数の加算ができます。

時計

+



"use strict";

const f = [["*","-","|","-","*","*","*","*"],["*","-","|","*","-","*","*","*"],["*","-","|","*","*","-","*","*"],["*","-","|","*","*","*","-","*"],["*","-","|","*","*","*","*","-"],["-","*","|","-","*","*","*","*"],["-","*","|","*","-","*","*","*"],["-","*","|","*","*","-","*","*"],["-","*","|","*","*","*","-","*"],["-","*","|","*","*","*","*","-"]];        

function abacus_operation(pos, add, a){
    if(add===1){
        if(a[pos][1]==="*"){
            [a[pos][0],a[pos][1]] = [a[pos][1],a[pos][0]];                           
            abacus_operation(pos+1, 3, a);
        }else{     
            [a[pos][0],a[pos][1]] = [a[pos][1],a[pos][0]];
        }
    }else{
        let count=3;
        while(a[pos][count]==="*"){
            count++;
        }        
        if(7-count<add-2){
            if(a[pos][1]==="*"){
                [a[pos][0],a[pos][1]] = [a[pos][1],a[pos][0]];
                for(let i=0; i<5-(add-2); i++){
                    [a[pos][count-i],a[pos][count-1-i]] = [a[pos][count-1-i],a[pos][count-i]];
                }
                abacus_operation(pos+1, 3, a);
            }else{
                [a[pos][0],a[pos][1]] = [a[pos][1],a[pos][0]];
                for(let i=0; i<5-(add-2); i++){
                    [a[pos][count-i],a[pos][count-1-i]] = [a[pos][count-1-i],a[pos][count-i]];
                }
            }
        }else{
            for(let i=0; i<add-2; i++){                
                [a[pos][count+i],a[pos][count+i+1]] = [a[pos][count+i+1],a[pos][count+i]];                
            }
        }
    }
}

document.getElementById("bt").onclick=function(){

    let num1_pre = document.getElementById("num1").value;
    let num2_pre = document.getElementById("num2").value;

    if(num1_pre.match(/^\d{0,5}$/) && num2_pre.match(/^\d{0,5}$/)){

        const num1 = num1_pre.split("");
        const num2 = num2_pre.split("");
        let a = [];
        let b = [];
        for(let i=num1.length-1; i>=0; i--){
            a.push([...f[num1[i]]]);            
        }
        for(let i=0; i<=5-num1.length; i++){
            a.push([...f[0]]);
        }
        for(let i=num2.length-1; i>=0; i--){
            b.push([...f[num2[i]]]);            
        }

        for(let i=b.length-1; i>=0; i--){
            for(let j=0; j<4; j++){
                if(j===0 || j===2){                        
                    continue;
                }
                else if(j===1){
                    if(b[i][1]==="*"){                                                  
                    abacus_operation(i, 1, a);
                    }                       
                }else{
                    let count = 3;
                    while(b[i][count]==="*"){
                        count++;
                    }
                    if(count!=3){                        
                        abacus_operation(i, count-1, a);
                    }
                }
            }
        }

        const result = document.getElementById("result");
        let a_ans = [];
        for(let i=0; i<a.length; i++){
            a_ans.push(a[i].join("")+"<br>");
        }
        result.innerHTML = a_ans.join("");
                        
        let ans = [];
        for(let i=5; i>=0; i--){
            for(let j=0; j<10; j++){
                if(a[i].toString()===f[j].toString()){
                    ans.push(j);
                    break;
                }
            }
        }
        const ans_num = document.createElement("div");
        ans_num.innerText = ans.join("");
        result.appendChild(ans_num);

    }else{
        const result = document.getElementById("result");
        result.innerHTML = "値が不正です。";
    }
}