割り算の筆算
Posted feedbacks - Nested
Flatten Hiddengauche 0.8.13です。
商の0になる桁の計算過程表示が冗長ですが・・・
gosh> (warizan 54321 5)
10864 ... 1
-----
5)54321
5
-----
4
0
-----
43
40
-----
32
30
-----
21
20
-----
1
#<undef>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | (define (warizan n m)
(define (printf format-str . data)
(display (apply format format-str data)))
(define (width data)
(string-length (format "~a" data)))
(define (num-at n scale)
(remainder (quotient n scale) 10))
(define (div-num x scale)
(let ((q (quotient x scale)))
(string-append
(make-string (- (+ (width n) (width m) 2)
(width q)
(width scale))
#\space)
(number->string q))))
(define (div-line)
(string-append
(make-string (+ (width m) 1) #\space)
(make-string (width n) #\-)))
(let* ((/ quotient) (q (/ n m)))
(printf "~a ... ~a\n~a\n~a)~a\n"
(div-num q 1)
(remainder n m)
(div-line)
m
n)
(let loop ((s0 (expt 10 (- (width n) 1))))
(let ((s1 (if (= s0 1) 1 (/ s0 10))))
(printf "~a\n~a\n~a\n"
(div-num (* m s0 (num-at q s0)) s0)
(div-line)
(div-num (- n (* m (/ q s0) s0)) s1))
(if (> s0 1)
(loop s1))))))
|
Squeak Smalltalk で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | | printWarizan |
printWarizan := [:n :m |
| width line quo rem isFirst |
n := n printString.
m := m printString.
width := n size + m size + 1.
line := String new: n size + 1 withAll: $-.
quo := n // m.
Transcript cr.
{quo. line. m, ')', n} do: [:each |
Transcript cr; show: (each forceTo: width paddingStartWith: $ )].
rem := ''.
isFirst := true.
n size to: 1 by: -1 do: [:idx |
| digit |
rem := rem copyWith: (n atLast: idx).
digit := (quo atLast: idx ifAbsent: [$0]) asString.
digit ~= '0' ifTrue: [
| elems |
elems := {rem. width - idx + 1. digit * m. width - idx + 1. line. width}.
isFirst ifTrue: [isFirst := false. elems := elems allButFirst: 2].
elems pairsDo: [:each :len |
Transcript cr; show: (each forceTo: len paddingStartWith: $ )]].
rem := rem - (digit * m)].
Transcript cr; show: (n \\ m forceTo: width paddingStartWith: $ )].
World findATranscript: nil.
printWarizan value: 123456 value: 77
"=>
1603
-------
77)123456
77
-------
464
462
-------
256
231
-------
25
"
|
Pythonでゴリゴリと。 文字列と整数の変換を繰り返したり、式が長かったり、無駄に条件分けがあったり、いろいろと汚いですが……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #!/usr/bin/python
# coding: utf-8
# aわるbを実装します
a = 123456
b = 77
# 割り算の筆算を表示する関数
def warizan(a, b):
# 数字の桁数を求める関数
digit = lambda x: len(str(x))
ans_div = a // b
ans_mod = a % b
print (digit(a) + digit(b) + 1 - digit(ans_div)) * ' ' + \
str(ans_div) + ' ... ' + str(ans_mod)
print digit(b) * ' ' + (digit(a) + 1) * '-'
print str(b) + ')' + str(a)
start = (digit(a) + digit(b) + 1 - digit(ans_div))
# 引く数
minuses = [int(str(ans_div)[i]) * b for i in range(digit(ans_div))]
# 引かれる数
minuend = int(str(a)[0:digit(a)-digit(ans_div)+1])
# 引いた後に下に下ろしてくる数字(aを一桁ずつ)
downs = [int(str(a)[i]) for i in range(digit(a) - digit(ans_div)+1, digit(a))]
downs.append(None)
for minus, down in zip(minuses, downs):
if minus != 0:
print (start + 1 - digit(minus)) * ' ' + str(minus)
print (start + 1 - max(digit(minuend), digit(minus))) * ' ' + \
(max(digit(minuend), digit(minus)) + 1) * '-'
start += 1
minuend = (minuend - minus)*10 + down if down != None else minuend - minus
if minuend >= b or down == None:
print (start + 1 - digit(minuend)) * ' ' + str(minuend)
# 関数呼び出し
if __name__ == '__main__':
warizan(a, b)
|
$ wari 12345 67
184
------
67)12345
67
------
564
536
------
285
268
------
17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | function wari() {
local -i m=$1
local -i n=$2
local r=$(printf '%*d' ${#m} $((m / n)))
write_head $m $n "$r"
write_body $m $n "$r"
}
function write_head() {
local m=$1
local n=$2
local r=$3
repeat_char ' ' $((${#n} + 1))
echo "$r"
write_bar $m $n
echo "$n)$m"
}
function write_body() {
local m=$1
local n=$2
local r=$3
local rest flag i
for ((i = 0; i < ${#r}; i++)) {
local c=${r:i:1}
rest="$rest${m:i:1}"
if [[ "$c" == [1-9] ]]; then
[ -n "$flag" ] && printf '%*d\n' $((i + ${#n} + 2)) $rest
printf '%*d\n' $((i + ${#n} + 2)) $((c * n))
write_bar $m $n
rest=$((rest - (c * n)))
flag=1
fi
}
[ -z "$flag" ] && write_bar $m $n
printf '%*d\n' $((i + ${#n} + 1)) $rest
}
function write_bar() {
local m=$1
local n=$2
repeat_char ' ' ${#n}
repeat_char - $((${#m} + 1))
echo
}
function repeat_char() {
local c=$1
local n=$2
while ((n--)); do
echo -n "$c"
done
}
|
JavaScriptで。手抜きHTMLに入れてありますが、このままでも大抵のブラウザで動くと思います。
どうせすっきり書けないだろうしというわけで、整数範囲で割れるだけ割るのに加えて、商の各桁について「0」以外が得られてからf桁に達したら筆算を止める(f桁に達しないうちは小数点以下になっても続ける)、というのも入れてみました。で、予想以上にごちゃごちゃ。
see: memo: 割り算の筆算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | <body>
<script>
function divOnPaper(n, m, maxFigs) {
n = Math.floor(Number(n)); n = (isNaN(n)||n < 1) ? 1 : n;
m = Math.floor(Number(m)); m = (isNaN(m)||m < 1) ? 1 : m;
maxFigs = Math.floor(Number(maxFigs)); maxFigs = (isNaN(maxFigs)||maxFigs < 0) ? 0 : maxFigs;
var q = [0], strQ = "", strN = n.toString(), qm, r = 0, exp = strN.length - 1;
var limitToInt = !maxFigs, firstFig = false;
var note = maxFigs ? "(up to " + maxFigs + " figures)" : "(within integer)",
rowQ, rowMN = insSP(m) + " ) " + insSP(n), rowsQMR = "", rowR0, rowR1;
while ((r || strN) && (limitToInt ? exp >= 0 : maxFigs)) {
r *= 10;
if (strN) {
r += Number(strN.substring(0, 1));
strN = strN.substring(1);
}
if (r >= m) {
rowR1 = repeatStr(" ", (rowMN.length - 2 * exp - insSP(r ).length)) + insSP(r );
if (firstFig) {rowsQMR += rowR1.substring(rowR0.length) + "\n";}
qm = r - r % m;
q[exp] = qm / m;
r = r % m;
rowsQMR += repeatStr(" ", (rowMN.length - 2 * exp - insSP(qm).length)) + insSP(qm) + "\n";
rowsQMR += repeatStr(" ", (rowMN.length - 2 * exp - insSP(qm).length) - 1);
rowsQMR += repeatStr("-", (insSP(qm).length) + 2) + "\n";
rowR0 = repeatStr(" ", (rowMN.length - 2 * exp - insSP(r ).length)) + insSP(r );
rowsQMR += rowR0;
firstFig = true;
} else {
if (firstFig || exp < 0) q[exp] = 0;
}
exp--;
if (firstFig) maxFigs--;
}
var i = exp; while (i > 0) q[i--] = 0;
i = q.length - 1; while (i >= 0) strQ += q[i--].toString();
if (typeof q[i] == 'number') strQ += ".";
while (typeof q[i] == 'number') strQ += q[i--].toString();
var summary = "n = m * q + r " + note + "\n" +
"n: " + n + "\n" +
"m: " + m + "\n" +
"q: " + strQ + "\n" +
"r: " + Number(r + "." + strN + "e" + (exp + 1));
rowQ = repeatStr(" ", (rowMN.length - insSP(strQ).match(/(?:\d| )+/)[0].length)) + insSP(strQ);
rowQ += "\n" + repeatStr(" ", insSP(m).length + 1) + repeatStr("-", (rowQ.length - insSP(m).length));
return summary + "\n\n" +rowQ + "\n" + rowMN + "\n" + rowsQMR + "\n\n\n";
function insSP(str) {
return str.toString().replace(/(\d)(?=\d)/g, "$1 ");
}
function repeatStr(str, num) {
return (new Array(num+1)).join(str);
}
}
</script>
<form>
n: <input id="n" type="text">
m: <input id="m" type="text">
f: <input id="f" type="text">
<input id="calc" type="button" value="calc"><br>
<textarea id="rslt" style="font-size: 0.8em; line-height: 0.9em; width: 100%; height: 30em;"></textarea>
</form>
<script>
function calc(){
n = document.getElementById("n").value;
m = document.getElementById("m").value;
f = document.getElementById("f").value;
document.getElementById("rslt").value = divOnPaper(n, m, f);
}
document.getElementById("calc").onclick = calc;
document.write("<h4>examples:</h4><pre style=\"font-size: 0.8em; line-height: 0.9em;\">" +
divOnPaper(1000, 71) + "\n" +
divOnPaper(1000, 71, 4) + "\n" +
divOnPaper(123456789, 57, 0) + "\n" +
divOnPaper(123456789, 57, 2) + "\n" +
divOnPaper(1000, 7, 0) + "\n" +
divOnPaper(1000, 7, 2) + "\n" +
divOnPaper(1000, 7, 3) + "\n" +
divOnPaper(1000, 7, 4) + "\n" +
"</pre>");
</script>
</body>
|
Javaで。割とコンパクトに書けたかな?
------
実行結果
10775
------
13)140077
13
------
100
91
-----
97
91
---
67
65
--
2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package doukaku;
import java.io.*;
public class Warizan {
public static void main(String[] args) {
print(new PrintWriter(new OutputStreamWriter(System.out)),140077, 13);
}
private static int xxx(int a) {
return (a < 10) ? 1 : 10 * xxx(a / 10);
}
public static void print(PrintWriter w, int a0, int b) {
int a = a0;
int indent = ("" + b).length() + 1;
String sp = (b + ")" + a).replaceAll(".", " ");
String bar = sp.replace(' ', '-');
w.printf("%s%" + ("" + a).length() + "d%n", sp.substring(0, indent), a / b);
w.printf("%s%s%n", sp.substring(0, indent), bar.substring(indent));
for (int c = xxx(a); c != 0; c /= 10) {
final int d = a / c;
final int e = (d / b) * b;
if (e == 0) continue;
final String ds = "" + d;
if (a == a0) w.printf("%d)%d%n", b, a);
else w.printf("%s%s%n", sp.substring(0, indent), ds);
w.printf("%s%" + ds.length() + "d%n", sp.substring(0, indent), e);
w.printf("%s%s%n", sp.substring(0, indent), bar.substring(indent));
indent += ds.length() - Integer.toString(d - e).length();
if(d == e) indent++;
a -= e * c;
}
w.printf("%" +sp.length() +"d%n", a);
w.flush();
}
}
|
15桁までしか対応しません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #!/usr/bin/perl
use strict;
use warnings;
div(@ARGV);
sub div{
return if scalar @_ != 2;
for(@_){ return unless /^[1-9]\d*$/; }
my ($x, $y) = @_;
my $line_length = length($x) + length($y) + 1;
my $ans = int($x / $y);
my $mod = $x % $y;
my $field_length = my $offset = length($y);
$field_length++;
printf "%${line_length}d\n", $ans;
print ' ' x $offset . '-' x ($line_length - $offset) ."\n";
print "$y)$x\n";
return if $ans == 0;
my @ans_nums = split //,$ans;
my @x = split //,$x;
my $dest_minus = '';
my $not_first_line = 0;
while(defined(my $ans_num = shift @ans_nums) && $offset++){
next if $ans_num == 0;
my $src_minus = $ans_num * $y;
$dest_minus .= shift @x while ($dest_minus || 0) < $src_minus;
printf ' ' x $offset . "%${field_length}d\n", $dest_minus if $not_first_line++;
printf ' ' x $offset . "%${field_length}d\n", $src_minus;
print ' ' x $offset . '-' x ($line_length - $offset) ."\n";
$dest_minus -= $src_minus;
$dest_minus = '' if $dest_minus == 0;
}
printf "%${line_length}d\n", $mod;
}
|
(warizan 9876 11)の結果 # ずれて見えるけど端末上では一応揃っている...
897 ... 9
-----
11 |9876
88
-----
107
99
-----
86
77
-----
9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | (defun warizan (n m)
(let* ((ret (floor (/ n m)))
(tochu n)
(calc-keta (lambda (x) (if (plusp x) (floor (log x 10)) 0)))
(string-concatenate (lambda (x &optional (s " ")) (apply 'concatenate 'string (make-list x :initial-element s))))
(keta (funcall calc-keta n))
(space-num (+ 3 (funcall calc-keta m)))
(keisen (format nil "~a~a~%" (funcall string-concatenate (1- space-num)) (funcall string-concatenate (+ 2 (funcall calc-keta n)) "-")))
)
(format t "~a~d ... ~d~%" (funcall string-concatenate (- (+ space-num keta) (funcall calc-keta ret))) ret (- n (* m ret)))
(format t keisen)
(format t "~d |~d~%" m n)
(dotimes (i (1+ keta))
(let* ((kurai (- keta i))
(p (* (floor (/ ret (expt 10 kurai))) (expt 10 kurai)))
(c (* p m))
)
(decf tochu c)
(decf ret p)
(when (> c 0)
(format t "~a~d~%" (funcall string-concatenate (- (+ space-num keta) (funcall calc-keta c))) (floor (/ c (expt 10 kurai))))
(format t keisen)
(format t "~a~d~%" (funcall string-concatenate (- (+ space-num keta) (funcall calc-keta tochu))) (floor (/ tochu (expt 10 (if (plusp kurai) (- kurai 1) kurai)))))
)
)
)
)
)
|
ふと無名関数が使いたくなったので、Visual Studio 2010 CTP付属のコンパイラを使いました。しかし、出来上がったものを見てみれば、ラムダ要らないのでは?という仕上がりですが、このまま投稿してしまいます。
除数・被除数を入力してください。
8956
12
0746
----
12)8956
0
----
89
84
----
55
48
----
76
72
----
4
答え合わせ: 8956 / 12の商・剰余は746 … 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include <iostream>
#include <sstream>
#include <iomanip> // setw
#include <string>
#include <cmath> // log10
#include <cstdlib> // div
int digit(int n)
{
return static_cast<int>(std::log10(static_cast<double>(n))) + 1;
}
std::ostream& print_c_n(std::ostream& os, char c, unsigned n)
{
for (unsigned i = 0; i < static_cast<unsigned>(n); ++i)
{
os << c;
}
return os;
}
void print_divition(int x, int y)
{
using namespace std;
ostringstream os;
os << y << ')';
unsigned left = static_cast<unsigned>(os.tellp());
os << x << '\n';
print_c_n(cout, ' ', left);
int digit_x = digit(x); // 十進法での桁数
// []の中は、外側の変数を「=」値渡し、ただしosのみ「&」参照渡しで受け取るの意
auto nextDigit = [=, &os](int r, int i) -> int
{
int u = x / static_cast<int>(pow(10., digit_x - i - 1)) % 10;
int t = r * 10 + u;
if (i != 0)
os << u << '\n';
div_t d = div(t, y);
std::cout << d.quot;
print_c_n(os, ' ', left) << std::setw(i + 1) << d.quot * y << '\n';
print_c_n(os, ' ', left);
print_c_n(os, '-', digit_x) << '\n';
print_c_n(os, ' ', left) << std::setw(i + 1) << d.rem;
return d.rem;
};
int r = 0;
for (int i = 0; i < digit_x; i++)
{
r = nextDigit(r, i);
}
cout << '\n';
print_c_n(cout, ' ', left);
print_c_n(cout, '-', digit_x);
cout << '\n' << os.str() << '\n';
div_t d = div(x, y);
cout << "答え合わせ: " << x << " / " << y << "の商・剰余は" << d.quot << " … " << d.rem << endl;
}
int main()
{
int m, n;
std::cout << "除数・被除数を入力してください。" << std::endl;
std::cin >> m >> n;
std::cout << '\n';
print_divition(m, n);
}
|
n と m を直接計算せずに求めています。
> divide 123456 77;;
1603
-------
77)123456
77
----
464
462
-----
256
231
---
25
val it : unit = ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #light
let divide n m =
let digits =
Seq.unfold (fun x -> if x > 0 then Some (x % 10, x / 10) else None)
>> Seq.to_list >> List.rev
let rec calc result index remainder = function
| [] -> (index - 1, remainder, None)::result |> List.rev
| n'::ns ->
let dividend = remainder * 10 + n'
calc ((index, dividend, Some (dividend / m))::result) (index + 1) (dividend % m) ns
let print result =
let length x = (string x).Length
let quotient =
result |> List.fold_left (fun sum (_, _, quot) ->
match quot with Some q -> sum * 10 + q | None -> sum) 0
let result' =
result |> List.filter (function _, _, Some q when q = 0 -> false | _, _, _ -> true)
let indent = length m + 1
let numbers =
result' |> List.mapi (fun i (index, dividend, quot) ->
let indent' = indent + index
(if i = 0 then "" else sprintf "%*d\n" indent' dividend) ^
(match quot with None -> "" | Some q -> sprintf "%*d\n" indent' (m * q)))
let lines =
result' |> Seq.pairwise |> Seq.to_list
|> List.map (fun ((index, dividend, _), (index', _, _)) ->
new string('-', index' - index + length dividend) |> sprintf "%*s\n" (indent + index'))
let width = indent + length n
printfn "%*d" width quotient
new string('-', length n + 1) |> printfn "%*s" width
printfn "%d)%d" m n
List.map2 (^) (""::lines) numbers |> String.concat "" |> printfn "%s"
digits n |> calc [] 1 0 |> print
|
*Main> :main 222222 111
2002
-------
111)222222
222
------
222
222
---
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | import Data.List ( mapAccumL, unfoldr )
import System.Environment ( getArgs )
longDivision :: Int -> Int -> String
longDivision n m = unlines $ showProcess n m $ getComponents n m
getComponents :: Int -> Int -> (Int, [Int], [Int], Int)
getComponents n m = (pack qs, ps, rs', last rs)
where
ns = unpack n
(qs, ps, rs) = unzip3 $ snd $ mapAccumL dm 0 ns
dm acc x = let { (q, r) = (10*acc + x) `divMod` m } in (r, (q, q*m, r))
rs' = [head ns] ++ zipWith ((+) . (10*)) (init rs) (tail ns)
showProcess :: Int -> Int -> (Int, [Int], [Int], Int) -> [String]
showProcess n m (q, ps, rs, r) = quot_divs ++ div_steps ++ remainder
where
[w_n, w_m] = map (length . show) [n, m]
w_mn = w_m + 1 + w_n
quot_divs = [ showR q, divLineR (w_n+1), show m ++ ")" ++ show n ]
div_steps = tail $ concat $ zipWith3 mkStep rs ps [w_m+2..]
remainder = [ showR r ]
mkStep _ 0 _ = []
mkStep r p k = [ showAt k r, showAt k p, divLineR (w_mn - k + length (show r)) ]
showR x = rjustify w_mn $ show x
divLineR w = rjustify w_mn $ replicate w '-'
-- misc
rjustify w xs = replicate (w - length xs) ' ' ++ xs
showAt w x = rjustify w $ show x
pack = foldl ((+) . (10*)) 0
unpack = reverse . unfoldr phi
where
phi 0 = Nothing
phi n = Just $ swap $ n `divMod` 10
swap (x,y) = (y,x)
main = do
args <- getArgs
let n:m:_ = map read args
putStr $ longDivision n m
|
出力例 (535325 / 423)
423)535325
1000 423000
-----------
112325
200 84600
-----------
27725
60 25380
-----------
2345
5 2115
-----------
230
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | static void Devide(int n, int m)
{
int q = n / m;
int lw = (int)Math.Log10(q > m ? q : m) + 1;
string lf = "{0," + lw.ToString() + "}";
int rw = (int)Math.Log10(n) + 1;
string rf = "{0," + rw.ToString() + "}";
string hl = new string('-', lw + 1 + rw);
Console.Write(lf, m);
Console.Write(')');
Console.WriteLine(rf, n);
for (int i = 0; i < lw; i++)
{
int d = lw - 1 - i;
int u = (int)Math.Pow(10, d);
int c = n / (u * m);
if (c == 0) continue;
int a = c * u;
int b = a * m;
Console.Write(lf, a);
Console.Write(' ');
Console.WriteLine(rf, b);
Console.WriteLine(hl);
n -= b;
Console.Write(lf, ' ');
Console.Write(' ');
Console.WriteLine(rf, n);
}
}
|
かなり愚直に実装してみました。
$ ruby divide.rb 312456 521
599
-------
521)312456
2605
-----
5195
4689
-----
5066
4689
----
377
2002
-------
111)222222
222
----
2
0
--
22
0
---
222
222
---
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | def divide(m, n) # m / n
digit = keta(m) - keta(n)
until (rem = m / (10**digit)) > n
digit -= 1
end
dend = rem
m1 = m % (10**digit)
history = []
digit.downto(0){|i|
base = 10 ** (i-1)
quot = dend / n
rem = dend % n
history << [dend, quot, quot*n]
dend = rem * 10 + m1 / base
m1 %= base
}
(d,_,h) = history[-1]
return history << [d - h, 0, 0]
end
def keta(n)
return 1 if n == 0
return Math.log10(n.to_i).floor + 1
end
if $0 == __FILE__
m, n ,= ARGV.map(&:to_i)
mketa = keta(m)
nketa = keta(n)
rslt = divide(m,n)
tochu, last = rslt[0..-2], rslt[-1]
width = mketa+nketa+1
printf "%#{width}s\n", tochu.map{|a|a[1]}.join("")
puts (" "*nketa)+("-"*(mketa+1))
printf "%d)%d\n", n, m
st = tochu.size - 1
tochu.each_with_index{|(dend, quot, hiku), ind|
k = nketa*2+2+ind
if ind > 0
printf "%#{k}d\n", dend
end
printf "%#{k}d\n", hiku
hosei = st == ind ? 0 : 1
hw = keta(dend) + hosei
printf "%#{k+hosei}s\n", "-" * hw
}
printf "%#{width}d\n", last[0]
end
|
sawatさんによるJava版の移植です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | int xxx(int a) {
(a < 10) ? 1 : 10 * xxx((int)a / 10);
}
Integer.metaClass.width = {(delegate as String).size()}
Integer.metaClass.padLeft = {n->(delegate as String).padLeft(n)}
def printexp(indent, exp, width) {
println(' '*indent + exp.padLeft(width))
println(' '*indent + '-'*width)
}
def waru(int a0, int b) {
int a = a0
int indent = b.width() + 1
printexp(indent, (int)a/b, a.width())
for (int c = xxx(a); c != 0; c /= 10) {
int d = a / c
int e = (d / b) * b
if (e == 0) continue
if (a == a0) println(b+")"+a)
else println('>' * indent+d)
printexp(indent, e, d.width())
indent += d.width() - (d - e).width()
if (d == e) indent++
a -= e * c
}
println(a.padLeft(b.width()+a0.width()+1))
}
waru(140077, 13)
|
Scalaらしく(?)作ってみました。#過去の課題でこっそり勉強中です。。
-- 実行結果
123456
77
1603
------
77)123456
77
------
464
462
------
256
231
------
25
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | object DivCalc {
def main(args : Array[String]) : Unit = {
val n = Console.in.readLine.toLong
val m = Console.in.readLine.toLong
Div(n, m).print
}
}
case class Div(n:Long, m:Long) {
def print = {
println( idt + fmt(ans) )
println( idt + line )
println( m + ")" + fmt(n) )
calc.take(1).foreach( x => println( idt + fmt(x._2, x._3) ) )
calc.drop(1).foreach( x => {
println( idt + line )
println( idt + fmt(x._1, x._3) )
println( idt + fmt(x._2, x._3) )
})
if (calc.isEmpty) println( idt + fmt(0) )
println( idt + line )
println( idt + fmt(mod) )
}
def len(a:Any) = a.toString.length
def fmt(x:Any):String = fmt(x, 0)
def fmt(x:Any, i:Int):String = idt(" ", len(n) - len(x) - i) + x
def line = idt("-", len(n))
def idt:String = idt(" ", len(m) + 1)
def idt(c:String, i:Int):String = c * i
val ans:Long = n / m
lazy val mod:Long = n % m
lazy val calc:List[(Long, Long, Int)] = {
def process(n:Long, m:Long, c:Int):List[(Long, Long, Int)] = {
val pow = Math.pow(10, c).toLong
val x = if (pow == 0) { 0L } else { n / pow / m * m }
(n,m,c,x) match {
case (_,_,c,_) if (c < 0) => Nil
case (n,m,c,0) => process(n, m, c-1)
case (n,m,c,x) => (n / pow, x, c) :: process(n - x * pow, m, c-1)
}
}
process(n, m, len(n))
}
}
|
F#で愚直な実装です。
> DivByHand 222222 111;;
2002
------
111)222222
222
------
222
222
------
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | //bDigDisp 3 "k" 2 で" kk"を表示
let bDigDisp padCount str strCount =
let rec sub subStr count limit res =
if count = limit then res
else sub subStr (count + 1) limit (res + subStr)
printfn "%s" ((sub " " 0 padCount "") + (sub str 0 strCount ""))
//numToList 1234 で[1;2;3;4]が返る
let numToList n =
let rec NtlSub m res =
if m = 0 then
res
else
NtlSub (m/10) ((m - (m/10)*10)::res)
NtlSub n []
let DivByHand num div =
let numList = numToList num
let divPadLen = (div.ToString()).Length + 1
let numLen = (num.ToString()).Length
bDigDisp (divPadLen + numLen - ((num/div).ToString()).Length) ((num/div).ToString()) 1
bDigDisp divPadLen "-" numLen
printfn "%d)%d"div num
let rec dbhSub (carryIn:int) (remDigLst:int list) (padLen :int) (isFirst : bool)=
match remDigLst with
| [] -> bDigDisp (padLen - (carryIn.ToString()).Length) (carryIn.ToString()) 1
| hd::tl -> let targetNum = 10*carryIn + hd
if targetNum < div then
dbhSub targetNum tl (padLen + 1) isFirst
else
let quoTemp = targetNum/div
let subNumStr = (div*quoTemp).ToString()
if(isFirst <> true) then
bDigDisp (padLen - (targetNum.ToString()).Length + 1 ) (targetNum.ToString()) 1
bDigDisp (padLen - subNumStr.Length + 1 ) subNumStr 1
bDigDisp divPadLen "-" numLen
dbhSub (targetNum % div) tl (padLen + 1) false
dbhSub 0 numList divPadLen true
|


rennos
#8785()
Rating7/7=1.00
[ reply ]