平成11年10月26日

[流れ星]

    第32回数学的な応募問題

 <解答募集期間:10月26日〜11月8日>

[素数・△数・□数]

 

 太郎さんは、「数学ができないから、嫌い」というやる気のない生徒をどのようにして引きつけるかを、考えながら授業をしています。「それは、いかにして生徒に感動を与えられるかにかかってきます。そのために教材や教具を使い、また、情報機器をも使っています。心への感動は、生徒が動いてくれることを信じていますから」。さらに、数学教師としてやりがいを持って、生徒に丁寧に接していくつもりです。生徒からの質問が大好きです。

 さて、今回の問題です。

「0から9までの数字を1列に並べ、隣り合う2数から9つの2桁の整数を作る。

このとき、この2数が整数が、素数なら3点、四角数なら2点、三角数なら1点

のように得点が与えることにする。

 できるだけ高い得点が得られるように、0から9までの数字を1列に並べてください。

例えば、1234567890の場合、左から順にできる9個の2桁の整数を調べると、

12…0点、 23…素数なので3点、 34…0点、 45…三角数なので1点

56…0点、 67…素数なので3点、 78…三角数なので1点、

89…素数なので3点、 90…0点

したがって、合計11点となる。ただし、次のことに注意してください。

@ たとえば、「02」は「2」とみなす。

A 四角数かつ三角数のときは、2+1=3点とする。

B 三角数とは、1,3,6,10,15,21,28,36,45,55,66,78,91 です。

C 四角数とは、1,4,9,16,25,36,49,64,81 です。

D 素数は自分で考えてください。

 <参考文献>:数とその歴史53話(上垣渉 何森仁 共著):三省堂 

 太郎さんは、一番高得点の並び方を実際知りません。生徒に、並べてもらって、得点を調べてもらおうと考えています。

 <ch3cooh>さんからの解答 10月26日受信 31日更新

 こんにちは、ch3coohです(毎度お世話になります)何か、答えを求める理論があるのかもしれませんが・・・

とりあえず、理論を思い付かなかったので、プログラムに実行させました。

 32問の答え(同一スコアの解答なし)

score : value-list

23 : 0 2 5 3 6 4 1 7 8 9

02:3

25:2

53:3

36:3

64:2

41:3

17:3

78:1

89:3

 プログラムのNを変更すると、N進数の場合について求めることが可能です。

例えば、8進数(同一スコア 多数)

16 : 0 2 1 3 4 5 7 6

9進数

25 : 6 5 2 1 8 7 4 0 3

25 : 6 5 8 7 4 0 3 2 1

25 : 6 7 4 0 3 2 5 8 1

25 : 6 7 8 1 4 0 3 2 5

 

12進数(同一スコアのリスト)

24 : 8 4 5 6 9 1 3 0 2 7 10 11

24 : 8 4 5 6 9 1 3 0 2 10 11 7

24 : 8 4 10 11 5 6 9 1 3 0 2 7

24 : 8 4 10 11 7 5 6 9 1 3 0 2

24 : 8 4 11 5 6 9 1 3 0 2 7 10

24 : 8 4 11 5 6 9 1 3 0 2 10 7

24 : 8 4 11 7 5 6 9 1 3 0 2 10

24 : 8 4 11 10 7 5 6 9 1 3 0 2

24 : 10 7 5 6 9 1 3 0 2 8 4 11

24 : 10 7 8 4 11 5 6 9 1 3 0 2

24 : 10 8 4 11 5 6 9 1 3 0 2 7

24 : 10 8 4 11 7 5 6 9 1 3 0 2

24 : 10 11 5 6 9 1 3 0 2 7 8 4

24 : 10 11 7 5 6 9 1 3 0 2 8 4

24 : 10 11 7 8 4 5 6 9 1 3 0 2

24 : 10 11 8 4 5 6 9 1 3 0 2 7

 20進数

計算時間がかかりすぎるので、あきらめたとなります。(プログラムは単純なループで作成していますが、

もう少し高速化の方法があるかもしれません。)この計算は、(現時点で)結構速いコンピュータで解いたため、

そこそこの時間で解答を得ることが出来ましたが、コンピュータが遅い時代では大変だったと思います。

 極限値を求める計算などでは、その収束のスピードが経済性に大きな影響を与えると思います。(最も顕著な例がπの算出)高校レベルでの微分・積分や極限値の算出では、収束の速度まで厳密に求めませんが、実用性のある知識とするには、誤差の程度や収束の速度の問題は重要な課題ではないでしょうか?

 以上  プログラム

#include <stdio.h>

#define N 10 int score_table[N*N] ;

void gen_tbl( void )

{int i, j ;for( i= 0 ; i< N*N ; i++ )

score_table[i]= 0 ;j= 1 ;

for( i= 2 ; j< N*N ; i++ )

score_table[j]= 1 ;j+= i ;}j= 1 ;

for( i= 3 ; j< N*N ; i+=2 )

{score_table[j]+= 2 ;j+= i ;}

for( i= 2 ; i< N*N ; i++ )

{for( j= 2 ; j*j< i ; j++ )

if ( i%j== 0 ) break ;

if ( j*j> i ) score_table[i]+= 3 ;}

#ifdef DEBUG3

for( i= 0 ; i< N*N ; i++ )

printf( "%3d : %d\n", i, score_table[i] ) ;

#endif}

intcount_score( int *value )

{int r, i, v ;r= 0 ;

for( i= 0 ; i< N-1 ; i++ )

{v= value[i]*N+value[i+1] ;

#ifdef DEBUG1

printf( "(%2d,%2d)", v, score_table[v] ) ;#endif

r+= score_table[v] ;}

#ifdef DEBUG1

printf( ":%4d\n", r ) ;

#endif

return r ;}

intmain( void )

{int i, j, max_score ;

int flags[N] ;

int list[N] ;

int max_list[N] ;

gen_tbl( ) ;

for( i= 0 ; i< N ; i++ )

{flags[i]= 0 ;}

i= 0 ;max_score= 0 ;

list[0]= -1 ;

do{list[i]++ ;

#ifdef DEBUG2

for( j= 0 ; j< i ; j++ ) putchar( ' ' ) ;

printf( "%2d : %2d\n", i, list[i] ) ;

#endif

if ( list[i]== N )

{i-- ;if ( i>= 0 ) flags[list[i]]= 0 ;

continue ;}

if ( flags[list[i]]== 0 )

{if ( i== N-1 )

{j= count_score( list ) ;

if ( max_score< j )

{max_score= j ;

for( j= 0 ; j< N ; j++ )

max_list[j]= list[j] ;

#ifdef DEBUG4

printf( "%4d :", max_score ) ;

for( j= 0 ; j< N ; j++ )

printf( "%2d", max_list[j] ) ;

putchar( '\n' ) ;

#endif}

} else {flags[list[i]]= i+1 ;

i++ ;list[i]= -1 ;}}}

while( i>= 0 ) ;

printf( "%4d :", max_score ) ;

for( i= 0 ; i< N ; i++ )

printf( "%2d", max_list[i] ) ;

putchar( '\n' ) ;

return 0 ;} 

<浜田明巳>さんからの解答 29日受信 31日更新       

 第32回数学的な応募問題[素数・△数・□数]解答

 早々と23点という答が出てしまった問題ですが,ようやく私も十進basicでの解答プログラムが出来上がったので,投稿します.工夫も全然していないプログラムで恥ずかしい限りですが,これが今のところ私の限界です.十進basicですと,解答が簡単にテキストファイルで掃き出されるので,これでプログラムを作ってみました.

 以下の7通りの場合があります.

23 0 2 5 3 6 4 1 7 8 9

23 0 2 5 3 6 4 1 9 7 8

23 0 2 5 9 7 8 3 6 4 1

23 8 3 6 4 1 0 2 5 9 7

23 8 3 6 4 7 1 0 2 5 9

23 8 9 7 1 0 2 5 3 6 4

23 8 9 7 3 6 4 1 0 2 5

!mondai32.bas

option base 0

dim j(9)

let max=0

for j0=0 to 9

let j(0)=j0

for j1=0 to 9

if j0<>j1 then

let j(1)=j1

for j2=0 to 9

if j0<>j2 and j1<>j2 then

let j(2)=j2

for j3=0 to 9

if j0<>j3 and j1<>j3 and j2<>j3 then

let j(3)=j3

for j4=0 to 9

if j0<>j4 and j1<>j4 and j2<>j4 and j3<>j4 then

let j(4)=j4

for j5=0 to 9

if j0<>j5 and j1<>j5 and j2<>j5 and j3<>j5 and j4<>j5 then

let j(5)=j5

for j6=0 to 9

if j0<>j6 and j1<>j6 and j2<>j6 and j3<>j6 and j4<>j6 and j5<>j6 then

let j(6)=j6

for j7=0 to 9

if j0<>j7 and j1<>j7 and j2<>j7 and j3<>j7 and j4<>j7 and j5<>j7 and j6<>j7 then

let j(7)=j7

for j8=0 to

if j0<>j8 and j1<>j8 and j2<>j8 and j3<>j8 and j4<>j8 and j5<>j8 and j6<>j8 and j7<>j8 then

let j(8)=j8

let j(9)=9

for jj=0 to 8

let j(9)=j(9)+jj-j(jj)

next jj

let ten=0

for jj=0 to 8

let check=10*j(jj)+j(jj+1)

let ten=ten+3*sosuu(check)

let suu=(sqr(1+8*check)-1)*0.5

let ten=ten+seisuu(suu)

let suu=sqr(check)

let ten=ten+2*seisuu(suu)

next jj

if ten>=max then

if ten>max then

let max=ten

print

end if

print max;

for jj=0 to 9

print j(jj);

next jj

print

end if

end if

next j8

end if

next j7

end if

next j6

end if

next j5

end if

next j4

end if

next j3

end if

next j2

end if

next j1

next j0

end

external function sosuu(x)

if x=1 then

let sosuu=0

else

let yakusuu=0

let j=2

do while yakusuu=0 and j<=int(sqr(x))

if mod(x,j)=0 then

let yakusuu=1

end if

let j=j+1

loop

let sosuu=1-yakusuu

end if

end function

external function seisuu(x)

if int(x)=x then

let seisuu=1

else

let seisuu=0

end if

end function

 素数問題なので,最初は素数の値を標準装備されている関数で簡単に求める事が出来るubasicでプログラムを組みました.しかし,DOSのプログラムではマルチタスクではないので,時間のかかる計算は不向きでしたので,Windowsのプログラムに移植した訳です.

<浜田明巳>さんからの解答その2 11月2日受信 3日更新

第32回数学的な応募問題[素数・△数・□数]解答その2

 前回十進basicで解答プログラムを作ったのですが,その後エクセルのマクロに移植し走らせたところ,十進basicのよりも計算スピードが早い事が分かりました.参考までにこのプログラムも投稿します.ワードのマクロに移植しても同様です.

23   0 2 5 3 6 4 1 7 8 9

23   0 2 5 3 6 4 1 9 7 8

23   0 2 5 9 7 8 3 6 4 1

23   8 3 6 4 1 0 2 5 9 7

23   8 3 6 4 7 1 0 2 5 9

23   8 9 7 1 0 2 5 3 6 4

23   8 9 7 3 6 4 1 0 2 5

Sub mondai32() 'mondai32

Dim j(9), j0, j1, j2, j3, j4, j5, j6, j7, j8, jj As Integer

Dim ten, check, max As Integer: max = 0

Dim suu As Double

Range("A1").Select

For j0 = 0 To 9: j(0) = j0

For j1 = 0 To 9

If j0 <> j1 Then

j(1) = j1

For j2 = 0 To 9

If j0 <> j2 And j1 <> j2 Then

j(2) = j2

For j3 = 0 To 9

If j0 <> j3 And j1 <> j3 And j2 <> j3 Then

j(3) = j3

For j4 = 0 To 9

If j0 <> j4 And j1 <> j4 And j2 <> j4 And j3 <> j4 Then

j(4) = j4

For j5 = 0 To

If j0 <> j5 And j1 <> j5 And j2 <> j5 And j3 <> j5 And j4 <> j5 Then

j(5) = j5

For j6 = 0 To 9

If j0 <> j6 And j1 <> j6 And j2 <> j6 And j3 <> j6 And j4 <> j6 And j5 <> j6 Then

j(6) = j6

For j7 = 0 To 9

If j0 <> j7 And j1 <> j7 And j2 <> j7 And j3 <> j7 And j4 <> j7 And j5 <> j7 And j6 <> j7 Then

j(7) = j7

For j8 = 0 To 9

If j0 <> j8 And j1 <> j8 And j2 <> j8 And j3 <> j8 And j4 <> j8 And j5 <> j8 And j6 <> j8 And j7 <> j8 Then

j(8) = j8

j(9) = 9: For jj = 0 To 8: j(9) = j(9) + jj - j(jj): Next

ten = 0

For jj = 0 To 8: check = 10 * j(jj) + j(jj + 1)

ten = ten + 3 * sosuu(check)

suu = (Sqr(1 + 8 * check) - 1) * 0.5

ten = ten + seisuu(suu)

suu = Sqr(check): ten = ten + 2 * seisuu(suu)

Next If ten >= max

Then

max = ten

ActiveCell.FormulaR1C1 = max

For jj = 0 To 9

SendKeys "{right}", True

ActiveCell.FormulaR1C1 = j(jj)

Next

SendKeys "{down}", True

For jj = 0 To 10: SendKeys "{left}", True: Nex

End If

End If

Next

End If

Next

End If

Next

End If

Next

End If

Next

End If

Next

End If

Next

End If

Next

Next

Beep

End Sub

Private Function sosuu(ByVal x As Integer) As Integer

Dim yakusuu, j As Integer

If x = 1 Then

sosuu = 0

Else

yakusuu = 0: j = 2

While yakusuu = 0 And j <= Int(Sqr(x))

yakusuu = -(x Mod j = 0): j = j + 1

Wend

sosuu = 1 - yakusuu

End If

End Function

Private Function seisuu(ByVal x As Double) As Integer

seisuu = -(Int(x) = x)

End Function

                     <自宅>  mizuryu@aqua.ocn.ne.jp

 最初のページへもどる