入れ子になった正方形を描くアルゴリズムとは?

このQ&Aのポイント
  • 正方形の入れ子構造を描くためのアルゴリズムについて学びましょう。
  • アルゴリズムの穴埋めや条件を理解することで、正方形の描画が可能になります。
  • 変数Lを用いて、枠の条件と文字の配置を確認しながらアルゴリズムを構築しましょう。
回答を見る
  • ベストアンサー

このアルゴリズムの解がわかりません。

入れ子になった正方形を描くアルゴリズムについて勉強しています。 添付の画像のように、「*」を用いて、入れ子構造になった正方形 を描く為のアルゴリズムを疑似言語で作る問題があります。 一番外側の枠を書く条件はわかるのですが、それ以外が考えても考えてもわかりません。 問題には以下のアルゴリズムの穴埋めを行いますが、埋まる内容とその理由を 教えていただけませんでしょうか? ここから --------------------------------------------------------------------------- procedure main: begin     I ← 1;     while I <= L do begin         J ← 1;         while J <= L do begin             if I が奇数である then                 if ***** 穴埋め「ア」 ***** then                     write "*"                 else if ***** 穴埋め「イ」***** then                     write "*"                 else if ***** 穴埋め「ウ」***** then                     write "*"                 else                     write " "             else                 if ***** 穴埋め「エ」***** then                     write " "                 else if ***** 穴埋め「イ」***** then                     write " "                 else if ***** 穴埋め「ウ」***** then                     write " "                 else                     write "*"             J ← J + 1         end;                  改行する;         I ← I + 1     end end --------------------------------------------------------------------------- ここまで 補足ですが、正方形の1辺の文字数は、変数Lに設定されており、その文字数は、この方法で正方形が描ける(7が最少で11、15...のように4つずつ増える)であるものとするみたいです。 どうかヒントだけでも構いませんので、 ご教授よろしくお願いいたします。

noname#229108
noname#229108

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

懐かしいですね、応用情報かソフ開か何かの過去問でしょうか? ぱっと見た感じ、Iで行を、Jで列を数えて、(I,J)に"*"と" "とのどちらの記号が来るかどうか判定し、表示しているように見えます。(イ)と(ウ)が2回登場しているにも関わらず出力が反転している、というところが大きな見どころでしょうか。 偶数行と奇数行とで出力が裏返っているのは行の中央の部分ですので、(ア)と(エ)でそれぞれそれ以外の部分を必要なだけ書いてしまう必要がありそうです。 else節を見てのとおり、このアルゴリズムでは、条件に漏れた部分に特定の記号が書かれるようになっているため、その逆の記号を何処に書いてあげるか、という情報を条件に含める必要がありそうです。 つまり、 Iが奇数の時:条件漏れした部分に" "が書かれるため、何処に"*"を書くかを決めてあげます。 Iが偶数の時:条件漏れした部分に"*"が書かれるため、何処に" "を書くかを決めてあげます。 ・(ア)では、Jが奇数の時は"*"を書く ・逆に(エ)では、Jが偶数の時には" "を書く として、残った部分のうち逆の記号がかかれては困る中央部分について ・(イ)では、I<L/2の時に行の中央部分が何処かを示す(I<=J かつ J<=L-I+1) ・逆に(ウ)では、I>L/2の時に行の中央部分が何処かを示す(L-I<J かつ J<=I) とするのが良いのではないでしょうか?

noname#229108
質問者

お礼

ご回答ありがとうございます。 わかりやすく説明していただきやっと理解することが出来ました!

その他の回答 (1)

  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.2

http://ideone.com/JcNucf class Q8131606 { public static void main(String[] args) { int L = 11; int I = 1; while (I <= L) { int J = 1; while (J <= L) { if (I % 2 == 1) { if (J % 2 == 1) { System.out.print("*"); } else if (I <= L/2 && I < J && J <= L-I) { System.out.print("*"); } else if (L-I < J && J < I) { System.out.print("*"); } else { System.out.print(" "); } } else { if (J % 2 == 0) { System.out.print(" "); } else if (I <= L/2 && I < J && J <= L-I) { System.out.print(" "); } else if (L-I < J && J < I) { System.out.print(" "); } else { System.out.print("*"); } } J = J + 1; } System.out.println(); I = I + 1; } } }

noname#229108
質問者

お礼

お久しぶりです。 ご回答ありがとうございます! プログラムまで書いていただき、デバックできて分り易かったです! 本当にありがとうございました!

関連するQ&A

  • Pascal言語で小町算

    Pascal言語で、『1~9の順に数字を並べ、+、-を補い式を作り、 値が100になる組み合わせをすべて出力するプログラムを作成せよ(例:12 - 3 - 4 + 5 - 6 + 7 + 89 = 100)。』 という課題が出ました。自分なりに組んでみたのですが、 12個あると聞いたのに、4個しか出力されません><; どこが間違っているのかご教授いただけると幸いですっ ------------------------------------------------------- program KomachiZan(output); var i,s:integer; var sign:array[1..9] of integer; var x,n:longint; begin writeln('< 小町算 -Komachi Zan- >'); for i:=1 to 9 do sign[i]:=-1; repeat x:=0; n:=0; s:=1; for i:=1 to 9 do begin if sign[i]=0 then n:=10*n+1 else begin x:=x+s*n; s:=sign[i]; n:=i; end; end; x:=x+s*n; if x=100 then begin for i:=1 to 9 do begin if sign[i]=1 then write(' + ') else if sign[i]=-1 then write(' - '); write(i); end; writeln(' = 100'); end; i:=9; s:=sign[i]+1; while s>1 do begin sign[i]:=-1; i:=i-1; s:=sign[i]+1; end; sign[i]:=s; until sign[1]>=1; end. -------------------------------------------------------

  • pascal二分木の課題

    レポート課題で、pascalの二分木についての問題が出たのですが、うまくソースコードを作ることができません! 誰かお手伝いよろしくお願いします! 課題:progに木をバランスよく組みなおす関数repackを追加せよ program prog(input,output); const maxRange = 100; type dataType = integer; tree = ^treeCall; treeCall = record data:dataType; left,right:tree end; var root:tree; command:char; value:dataType; function search(d:dataType; t:tree):tree; begin if t=nil then search:=nil(*ブレーク*) else if t^.data=d then search:=t(*見つけた*) else if t^.data>d then search:=search(d,t^.left)(*左を検索*) else search:=search(d,t^.right)(*右を検索*) end; procedure insert(d:dataType; var t:tree); begin (**) if t=nil then begin new(t); t^.data:=d; t^.left:=nil; t^.right:=nil end else if t^.data=d then (*すでに登録されているので何もしない*) else if t^.data>d then insert(d,t^.left) else insert(d,t^.right); end; procedure delete(d:dataType; var t:tree); var temp:tree; procedure deleteMin(var r:tree); var temp:tree; begin temp:=r; while temp^.left<>nil do temp:=temp^.left; t^.data:=temp^.data; delete(temp^.data,r) end; begin if t=nil then writeln('Not Exist.') else if t^.data=d then if (t^.left<>nil) and (t^.right<>nil) then deleteMin(t^.right) else begin temp:=t; if t^.left<>nil then t:=t^.left else t:=t^.right; dispose(temp); end else if t^.data>d then delete(d,t^.left) else delete(d,t^.right) end; procedure writeSet(t:tree); begin if t=nil then (*何もしない*) else begin writeSet(t^.left);(*左へ左へ・・・*) write(t^.data:1,' '); writeSet(t^.right)(*右へ・・・*) end end; (****** Body ******) begin root:=nil; repeat write('> '); read(command); if command in ['i','d','s','w'] then begin (*もしもコマンドがw以外なら値を読み込む*) if command='w' then readln else readln(value); case command of (*数値をバイナリーツリーに挿入 ここでソーティングしたい*) 'i': insert(value,root); 'd': delete(value,root);

  • クイックソート後の出力(pascal)

    20個の整数データをクイックソートして出力せよ、という課題が出ました。クイックソートまでは出来た(コンパイルできたのでおそらく)のですが、その順に出力する方法がわかりません。どなたかお教えください。 program sort(input,output); const n = 20; type index = 1..n; var A : array[1..n] of integer; i,x,a : integer; p,j,k : index; function PIVOT(i,j : index):integer; var k:index; begin k:=i+1; while (A[i]=A[k]) and (k<=j) do k:=k+1; if k>j then PIVOT:=0 else if A[i]>=A[k] then PIVOT:=i else PIVOT:=k end; procedure SWAP(var x,y:integer); var temp:integer; begin temp:=x; x:=y; y:=temp end; procedure PARTITION(i,j:index; a:integer; var k:index); var l,r:index; begin l:=i; r:=j; while A[l]<a do l:=l+1; while A[r]>=a do r:=r-1; while l<=r do begin SWAP(A[l],A[r]); l:=l+1; r:=r-1; while A[l]<a do l:=l+1; while A[r]>=a do r:=r-1; end; k:=l end; procedure QUICKSORT(i,j:index); var a:integer; p:index; k:index; begin p:=PIVOT(i,j); if p<>0 then begin a:=A[p]; PARTITION(i,j,a,k); QUICKSORT(i,k-1); QUICKSORT(k,j) end end; begin i:=0; i:=1+1; for i:= 1 to n do begin A[i]:=0; end; i:=0; i:=i+1; for i:= 1 to n do begin readln(x); A[i]:=x end; a:=PIVOT(p,j); PARTITION(p,j,A[a],k); QUICKSORT(p,j) end. QUICKSORT(p,j)とend. の間に出力方法を書き込みたいのです。

  • 二分法の近似解について

    二分法の近似解について 問題の解釈に自信が持てません。 お手数をお掛けします 以下問題です。 ”f(x)=x^2-a (aは正数とする)として、二分法によって方程式f(x)=0の 近似解を小数点以下4桁まで正しく求めるプログラムを作成せよ。” というものですが、これはaの平方根を小数点以下四桁まで求めろと解釈すればいいのですか? 主にプラス側とマイナス側からその差を0に収束するイメージがあります。 あと、aは何らかの数値を代入して良いものと解釈しました。 代入しないとアルゴリズムとして成立しませんよね? 以下コード(basic)です。 PRINT "f(x)=x^2-aのaを入力" INPUT a PRINT "区間の両端を入力" INPUT i INPUT j IF (i^2-a)*(j^2-a)<0 THEN DO WHILE ABS(i-j)>=0.00001 LET m=(i+j)/2 IF (i^2-a)*(m^2-a)<0 THEN LET j=m ELSE LET i=m END IF LOOP PRINT "f(x)=0の近似解はx=";i ELSE PRINT "両端の符号が同一です" END IF END

  • Select case で条件演算子は使用可能?

     知っている方にはつまらない質問でしょうが…VB6.0でSelect case に条件演算子を使う事ってできないんでしょうか?  つまり、 if i < 0 then j = 0 else if i = 0 then j = 1 else if i > 0 then j = 2 end if  こんな感じの条件をSelect Caseで使えませんか?と言うことなんですが…

  • EXCEL インデックスが有効範囲にありません

    エクセルでマクロを使ったソフト(他人が作ったもの)を使っているのですが、 計算の途中で「インデックスが有効範囲にありません」という エラーが出てしまい困っています。 同じ量の他の数値(サンプル数91、属性9)でやるとエラーがでないのですが、今やっている文字列のときだけエラーが出るといった場合 何が考えられるでしょうか?以下はデバッグ結果です。 'For j = 2 To M - 1 '列に関する繰り返し MaxMax = MaxI iflag = 0 For j = 2 To iR - 1 '上限? kkk = 1 For i2 = 1 To MaxI For i = 1 To MaxMax If C(i) = "" Or B(i2, j) = "" Then 'Exit For Else If Trim(C(i)) = Trim(B(i2, j)) Then D(kkk) = B(i2, j) B(i2, j) = "" kkk = kkk + 1 Else If InStr(1, C(i), B(i2, j), 1) <> 0 Then D(kkk) = C(i) C(i) = "" kkk = kkk + 1 iflag = 1 End If End If End If Next i 'If iflag = 1 Then ' B(i2, j) = "" ' iflag = 0 'End If Next i2 For i = 1 To MaxMax For i2 = 1 To MaxI If C(i) = "" Or B(i2, j) = "" Then 'Exit For Else D(kkk) = C(i) & B(i2, j) kkk = kkk + 1 End If Next i2 Next i For i = 1 To kkk - 1 '簡略,exp.P and TP,, For i2 = 1 To kkk - 1 If i <> i2 And D(i) <> "" And D(i2) <> "" Then If Len(D(i)) > Len(D(i2)) Then L1 = Len(D(i)) L2 = Len(D(i2)) If Comp(D(i), D(i2), L1, L2) = 1 Then D(i) = "" 'Exit For End If Else L2 = Len(D(i)) L1 = Len(D(i2)) If Comp(D(i2), D(i), L1, L2) = 1 Then D(i2) = "" 'Exit For End If End If End If Next i2 Next i i2 = 1 For i = 1 To kkk - 1 If D(i) <> "" Then Cells(i2, iR + j) = D(i) C(i2) = D(i) ←ここがエラー i2 = i2 + 1 End If Next i MaxMax = i2 - 1 Next j 上記文章だけでは何も分からないとは思うのですが、 何か分かる方がいらっしゃればお願いいたします。

  • アルゴリズム(2分探索木)の問題について

    2分探索木のアルゴリズムに関する問題について質問させていただきます。 [問題] 集合Sに対する2文探索木とは、ラベルつきの2分木で、 その頂点vにはSのある要素l(v)がラベルとしてつけられている。 l(v)は次の性質を満たす。 1.vの左部分木の頂点uに対して l(u) < l(v) 2.vの右部分木の頂点uに対して l(u) > l(v) 3.Sの任意の要素aに対して l(v) = a となる頂点vはちょうどひとつある。 図はキーワード集合{begin,else,end,if,then}をあらわす2分探索木の例である。 いま、集合Sを表す2分探索木と要素aが与えられているときa∈Sならば"はい"、 そうでなければ"いいえ"を出力するアルゴリズムを考える。 このアルゴリズムは、木の根rについて一回だけ再帰手続きSEARCH(a,r)を呼び出せばよい。 ただし、SEARCH(a,v)はvを根とする部分木中に要素aが含まれているかを判定する。 含まれているときに値"はい"を、そうでなければ値"いいえ"を返す。 ・アルゴリズム procedure SEARCH(a,v): if a = l(v) then return "はい" else if a < l(v) then if vが左の子wを持つ then return SEARCH( ア ) else return "いいえ" else イ 以下の問題に答えよ。 (1) 上のアルゴリズムのア,イを埋めよ。 (2) 上のアルゴリズムを参考にして、集合Sからのデータの削除DELETE(a,S)を考える。 削除すべき要素aが頂点vのラベルであったとする。そのとき次の3つの場合について、行うべき操作を記述せよ。 (i) 頂点vが葉である (ii) 頂点vの子が1個ある (iii) 頂点vの子が2個ある 以上です。 設問(1)は解けました。 答えは ア: a,w イ: a > l(v) then if vが右の子wを持つ then return SEARCH(a,w) else return "いいえ" になるのではないかと思います。 設問(2)についてなのですが、それぞれの場合について、どのような操作をすればよいのかは、 参考書などを読んで理解したのですが、どのように記述したらよいかがわかりません。 長文になってしまい申し訳ないのですが、回答よろしくお願いいたします。

  • さっきのバイナリ→テクスト

    FP1 = FreeFile Open Text1.Text For Binary As #FP1 FP2 = FreeFile Open Text3.Text For Output As #FP2 Do While (Not (EOF(FP1))) For i = 1 To 128 Get #FP1, , Bwk(i) Next i flg = 0 If j(1) <> "" Then Swk = Right("00" & Trim(Hex(Bwk(1))), 2) & Right("00" & Trim(Hex(Bwk(2))), 2) For i = 1 To 5 If j(i) <> "" Then If j(i) = Swk Then flg = 1 Exit For End If End If Next i Else flg = 1 End If If flg = 1 Then Swk = "" For i = 1 To 128 Swk = Swk & Right("00" & Trim(Hex(Bwk(i))), 2) Next i Print #FP2, Swk End If Loop Close MsgBox "完了" End Sub 上のプログラムでどこで変換してるのかがわからないんです。誰か教えてください。

  • sortアルゴリズムにおけるstack操作

    あるサイトさんを参考にしてstackを用いたソートアルゴリズムを作っていたのですが、先ほど偶然完成してしまいました。 スタックの動きがよく分からないまま出来てしまったので何だか腑に落ちません・・・ (参考にしたサイトさんも解説がありませんでした) よろしければ(1)~(3)の部分の解釈を教えていただけないでしょうか? よろしくお願いしますm(_ _)m void sort(int A[], int a, int b) /* 昇順整列 */ { int i, j; int pvt; /* 枢軸 */ int sp = 0; /* スタックポインタ */ int left_stc[64], right_stc[64]; while(FOREVER){ pvt = a[b], i = a, j = b-1; while(i < j){ while(A[i] < pvt) i++; while(A[j] > pvt) j--; if(i < j){ swap(&A[i], &A[j]); i++; j--; } } if(A[i] > pvt) swap(&A[i], &A[b]); (1)if(a < i-1){ left_stc[sp] = i; right_stc[sp++] = b; b = i-1; continue; } (2)if(i+1 < b){ a = i+1; continue; } (3)else{ if((sp--) <= 0) break; a = left_stc[sp]; b = right_stc[sp]; continue; } } }

  • エクセルVBAを修正したい

    数字を入力すると記号に変換になるマクロを 元ファイルを修正して作成したいのですが、 同一シートにC9:M33,C9:Y25,O27:Y29といった 範囲の異なる表がある場合はセル範囲をどのように記述すれば良いでしょうか? StartCol = 4 '開始列 EndCol = 20 '終了列 BlankCount = 0 I = 16 '開始行 L = 14 '行の指定 Do While Len(Range("B" & CStr(I)) & Range("C" & CStr(I))) > 0 For J = StartCol To EndCol If Len(ActiveSheet.Cells(L, J).Value & ActiveSheet.Cells(L + 1,J).Value) > 0 Then tmp = "" If ActiveSheet.Cells(I, J).Value = "×" Or ActiveSheet.Cells(I,J).Value = "中止" Then Else If Len(ActiveSheet.Cells(I, J).Value) = 0 Then K = -1 Else K = ActiveSheet.Cells(I, J).Value End If Select Case K Case 0 tmp = "×" Case 1 To 14 tmp = "△" Case Is >= 15 tmp = "○" End Select End If Next I = I + 1 If Len(Range("B" & CStr(I)) & Range("C" & CStr(I))) = 0 Then L = I + 1 I = I + 3 End If Loop End Sub

専門家に質問してみよう