大富豪家2.0の日記全体に公開

2005年08月28日
19:05
 1,3,4,6と四則演算で
24を作る方法を考えろ、という問題を思い出した。
「切符問題」の一種だが結構難しい。お暇なときにどうぞ。
 

コメント    

2005年08月28日
19:48
i16(愛一郎)@一陽來復
おお。パスネットとスイカに移行したら切符問題が出題されなくなっていたのか。(笑)
2005年08月28日
20:59
Portercircle
数字は1度しか使ってはいけないのですか?
2005年08月28日
21:35
大富豪家2.0
各数字は一度ずつです。じゃなきゃ簡単すぎる...
e.g. 6×4+3−1=26
2005年08月28日
23:48
とょだ
22と26はできたのですが24ができません。うーん。
1、1、9、9で10というのは有名ですよね。
2005年08月28日
23:53
大富豪家2.0
(1+1/9)×9 とか?
2005年08月29日
01:55
とょだ
です。24できました。1,1,9,9よりひねりが効いていて面白いですね。
2005年08月29日
08:03
大富豪家2.0
お、速いですね! 私は相当悩みました...
2005年08月29日
12:22
まえG
ついプログラムで解いてしまう。
2005年08月29日
12:50
和風(ナチ)
プログラム書いてといちゃいました
できあいなのですごい汚いperlスクリプトですけど

$numbers = [1,3,4,6];
$ope = ["+","-","*","/"];

$opeList;
$numbersList;

make_perm(4);
make_perm2(4);


for(my $i = 0 ; $i < @$numbersList ; $i++){
for(my $j = 0 ; $j < @$opeList ; $j++){

setop($numbersList->[$i],$opeList->[$j]);
}
}


sub make_perm2 {
my $n = shift;
my $i = 1;
for( ; $i <= $n; $i++ ){
push( @perm, $i );
if( $n-1 == @perm ){
push @$opeList ,[@perm];
} else {
$table[$i] = 1;
&make_perm2( $n );
$table[$i] = 0;
}
pop( @perm );

}
}


sub make_perm {
my $n = shift;
my $i = 1;
for( ; $i <= $n; $i++ ){
unless( $table[$i] ){
push( @perm, $i );
if( $n == @perm ){
push @$numbersList ,[@perm];
} else {
$table[$i] = 1;
&make_perm( $n );
$table[$i] = 0;
}
pop( @perm );
}
}
}

sub setop{
my $nums = shift;
my $ops = shift;

for(my $j = 0 ; $j < 3 ; $j++){
my $statement = "(";
for(my $i = 0; $i < 3 ; $i++){

$statement .= $numbers->[$nums->[$i]-1];
if($i==$j){
$statement.=")";
}
$statement .= $ope->[$ops->[$i]-1];
if($i==$j){
$statement.="(";
}
}
$statement .= $numbers->[$nums->[3]-1].")";
if(eval($statement) == 24){
print $statement."\n";
}
}
}
2005年08月30日
09:58
enNetforum遠山
おはようございます。
なんとなく出来てしまいました。答は一種類だけかな?

上のプログラム、すごそうですね。数字の並びの組み合わせ&四則演算全通り?
昔はこんな計算でも時間がかかったような。
2005年08月31日
01:28
せ"
6 を引っくり返して 9 にするのはありでしょうか(笑)

24 = 1 + 9 x 3 - 4
2005年08月31日
10:16
enNetforum遠山
うーん、昔、ジミ・ヘンドリックスの曲で、
"If 6 Was 9" というのがあったような。
2005年08月31日
16:24
大富豪家2.0
def add(s) s.push(s.pop + s.pop) end
def sub(s) v = s.pop; s.push(s.pop - v) end
def mul(s) s.push(s.pop * s.pop) end
def div(s) v = s.pop; s.push(s.pop / v) end

def calc(list)
s = []
list.each { |v|
v.class == Symbol ? method(v).call(s) : s.push(Float(v))
}
s
end

def check0(list,args,nop,ops,res)
if args.length == 0 && nop == 0 then
puts list if calc(list)[0] == res
else
if calc(list).length >= 2 && nop > 0 then
ops.each { |op|
check0(list.dup.push(op),args,nop-1,ops,res)
}
end
args.each { |arg|
args2 = args.dup
args2.delete(arg)
check0(list.dup.push(arg),args2,nop,ops,res)
}
end
end

def check(args,ops,res)
check0([],args,args.length-1,ops,res)
end

check([1,3,4,6],[:add, :sub, :mul, :div],24.0)
2005年08月31日
17:52
まえG
Rubyですか。
でも、これだと「5,5,5,5から24を作れ」の解が見つけられないような?
2005年08月31日
19:09
大富豪家2.0
あ、deleteの仕様を勘違いしてました...スマソ
2005年08月31日
20:02
まえG
args2.delete_at(args2.index(arg))
とすれば良いんですかね。
2005年08月31日
23:58
大富豪家2.0
うまくいきました。thank you!

def add(s) s.push(s.pop + s.pop) end
def sub(s) v = s.pop; s.push(s.pop - v) end
def mul(s) s.push(s.pop * s.pop) end
def div(s) v = s.pop; s.push(s.pop / v) end

def calc(list)
s = []
list.each { |v|
v.class == Symbol ? method(v).call(s) : s.push(Float(v))
}
s
end

def check0(list,args,nop,ops,res)
if args.length == 0 && nop == 0 then
puts list if calc(list)[0] == res
else
if calc(list).length >= 2 && nop > 0 then
ops.each { |op|
return if check0(list.dup.push(op),args,nop-1,ops,res)
}
end
args.each { |arg|
args2 = args.dup
args2.delete_at(args2.index(arg))
return if check0(list.dup.push(arg),args2,nop,ops,res)
}
false;
end
end

def check(args,ops,res)
check0([],args,args.length-1,ops,res)
end

check([1,3,4,6],[:add,:sub,:mul,:div],24.0)
check([5,5,5,5],[:add,:sub,:mul,:div],24.0)
check([1,1,9,9],[:add,:sub,:mul,:div],10.0)
2005年09月01日
11:18
まえG
Schemeだとこんな感じ。ゼロ除算を無視するwith-error-handlerはgauche依存。

(define ops `((,+ . +) (,- . -) (,* . *) (,/ . /)))

(define (make-tree l make-node)
  (if (null? l) '()
    (let ((r (make-tree (cdr l) make-node)))
     (if (number? (car l))
       (cons (car l) r)
       (cons (make-node (car l) (car r) (cadr r))
          (cddr r))))))
(define (execute l)
  (make-tree l (lambda (op left right) (op left right))))

(define (print l)
  (make-tree l (lambda (op left right)
          `(,left ,(cdr (assoc op ops)) ,right))))

(define (try nums ans)
  (let ((limit (- (* 2 (length nums)) 1)))
   (define (generate num-ops num-nums l nums)
     (define (try-op)
       (for-each (lambda (op)
             (generate (+ num-ops 1) num-nums
                  (cons (car op) l) nums))
            ops))
     (define (try-num)
       (do ((n1 nums (cdr n1))
          (n2 '() (cons (car n1) n2)))
         ((null? n1))
        (generate num-ops (+ num-nums 1)
             (cons (car n1) l)
             (append (cdr n1) n2))))
    (if (= limit (+ num-ops num-nums))
      (with-error-handler (lambda (ignore) ignore)
       (lambda ()
        (if (= (car (execute l)) ans)
          (begin
           (display (car (print l)))
           (newline)))))
      (begin
       (if (< num-ops (- num-nums 1)) (try-op))
       (if (not (null? nums)) (try-num)))))
   (generate 0 0 '() nums)))

; (try '(1 1 9 9) 10)
; (try '(1 3 4 6) 24)
2005年09月01日
19:04
綾塚
しばらく考えて、ようやくできました。
なるほど、そう来たか、って感じですね。