過去ログ

                                Page      69
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   通常モードに戻る  ┃  INDEX  ┃  ≪前へ  │  次へ≫   
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ▼計算式をつくるには  おらんじゅ 02/9/10(火) 22:20
   ┣Re:計算式をつくるには  こうちゃん 02/9/11(水) 10:10
   ┣大きく分けて2通り  JuJu 02/9/11(水) 13:14
   ┗Re:計算式をつくるには  禰宜 02/9/11(水) 23:00
      ┗Re:計算式をつくるには  おらんじゅ 02/9/12(木) 21:08

 ───────────────────────────────────────
 ■題名 : 計算式をつくるには
 ■名前 : おらんじゅ
 ■日付 : 02/9/10(火) 22:20
 -------------------------------------------------------------------------
    ab
× c
~~~~~~
 de
+fg
~~~~~~
 hi


という式で、a〜iまでに1〜9の数字を一度だけ使用して
計算式を成り立たせたいのですが、 VBAではどのようにつくったらいいのでしょうか。

関数などで考えてみたのですが、どうしても出来ません。
よろしくお願いいたします。
 ───────────────────────────────────────  ■題名 : Re:計算式をつくるには  ■名前 : こうちゃん <nakajima19@hotmail.com>  ■日付 : 02/9/11(水) 10:10  -------------------------------------------------------------------------
   おらんじゅ さん、こんにちは

> ab
>× c
>~~~~~~
> de
>+fg
>~~~~~~
> hi
>
>という式で、a〜iまでに1〜9の数字を一度だけ使用して
>計算式を成り立たせたいのですが、 VBAではどのようにつくったらいいのでしょうか。
>
>関数などで考えてみたのですが、どうしても出来ません。
>よろしくお願いいたします。


かなり冗長ですが、ゴリゴリとプロシージャ作ってみました。
標準モジュールに貼り付けて、実行してみてください。

ロジックももっとエレガントにしないといかんですが・・・^^;

#このロジックでは組み合わせは1通りしか探せなかったけど、正解かなぁ(??)

Sub test()
  Dim j As Integer
  Dim k As Integer
  Dim l As Integer
  Dim m As Integer
  Dim n As Integer
  Dim DE As Integer
  Dim HI As Integer
  
  For j = 1 To 9
    For k = 1 To 9
      For l = 1 To 9
        DE = ABCD(Trim(CStr(j)), Trim(CStr(k)), Trim(CStr(l)))
        If DE > 0 Then
          For m = 1 To 9
            For n = 1 To 9
              HI = DEFG(Trim(CStr(j)), Trim(CStr(k)), _
              Trim(CStr(l)), Left(Trim(CStr(DE)), 1), _
              Right(Trim(CStr(DE)), 1), Trim(CStr(m)), _
              Trim(CStr(n)))
              If HI > 0 Then
                MsgBox j & k & l & _
                  Left(Trim(CStr(DE)), 1) & _
                  Right(Trim(CStr(DE)), 1) & _
                  m & n & _
                  Left(Trim(CStr(HI)), 1) & _
                  Right(Trim(CStr(HI)), 1)
              End If
            Next
          Next
        End If
      Next
    Next
  Next

End Sub

Function DEFG(A As String, B As String, C As String, _
       D As String, E As String, F As String, G As String) As Integer

  Dim DE As Integer
  Dim FG As Integer
  Dim HI As Integer
  Dim HH As String
  Dim II As String
  
  DE = CInt(D & E)
  FG = CInt(F & G)
  HI = DE + FG
  
  If A = B Or A = C Or A = D Or A = E Or A = F Or A = G _
    Or B = C Or B = D Or B = E Or B = F Or B = G _
    Or C = D Or C = E Or C = F Or C = G _
    Or D = E Or D = F Or D = G _
    Or E = F Or E = G _
    Or F = G _
    Then
    DEFG = 0
    Exit Function
  End If
  
  
  If HI > 98 Then
    DEFG = 0
  Else
    HH = Left(Trim(CStr(HI)), 1)
    II = Right(Trim(CStr(HI)), 1)
    If HH <> A And HH <> B And HH <> C And HH <> D And _
      HH <> E And HH <> F And HH <> G And _
      II <> A And II <> B And II <> C And II <> D And _
      II <> E And II <> F And II <> G And _
      HH <> II And _
      HH <> "0" And _
      II <> "0" _
      Then
      DEFG = HI
    Else
      DEFG = 0
    End If
  End If

End Function

Function ABCD(A As String, B As String, C As String) As Integer
  Dim AB As Integer
  Dim DE As Integer
  Dim DD As String
  Dim EE As String
  
  AB = CInt(A & B)
  DE = AB * CInt(C)
  
  If A = B Or A = C Or B = C Then
    ABCD = 0
    Exit Function
  End If
  
  If DE > 87 Then
    ABCD = 0
  Else
    DD = Left(Trim(CStr(DE)), 1)
    EE = Right(Trim(CStr(DE)), 1)
    If DD <> A And DD <> B And DD <> C And _
      EE <> A And EE <> B And EE <> C And _
      DD <> EE And _
      DD <> "0" And _
      EE <> "0" _
      Then
      ABCD = DE
    Else
      ABCD = 0
    End If
  End If
  
End Function
 ───────────────────────────────────────  ■題名 : 大きく分けて2通り  ■名前 : JuJu <juju-bbs@su-u.com>  ■日付 : 02/9/11(水) 13:14  -------------------------------------------------------------------------
   おらんじゅさん、こんにちはぁ

> ab
>× c
>~~~~~~
> de
>+fg
>~~~~~~
> hi
>という式で、a〜iまでに1〜9の数字を一度だけ使用して
>計算式を成り立たせたいのですが、 VBAではどのようにつくったらいいのでしょうか。

方法は大きく分けて2種類あります。
 1.1〜9の数字を全パターン入れて、式が正しいか評価する。
 2.式が正しい数字を入れて、1〜9の数字になっているか評価する。

ほとんどの場合、2の方が繰り返し回数が少ないので速いです。


1.1〜9の重複しない数字を求める方法はいろいろありますが、一例として、

Sub Macro1()

  Shuffle "123456789"
End Sub

Sub Shuffle(ByVal strData As String, Optional ByVal lngNum As Long = 1)
  Dim strTmp As String
  Dim strC As String
  Dim i As Long

  If lngNum < Len(strData) Then
    '' シャッフル
    For i = lngNum To Len(strData)
      strTmp = strData
      If i <> lngNum Then
        strC = Mid(strTmp, i, 1)
        Mid(strTmp, i, 1) = Mid(strTmp, lngNum, 1)
        Mid(strTmp, lngNum, 1) = strC
      End If
      Shuffle strTmp, lngNum + 1
    Next
  Else
    '' 判定
    If CLng(Mid(strData, 1, 2)) * CLng(Mid(strData, 3, 1)) = CLng(Mid(strData, 4, 2)) And _
      CLng(Mid(strData, 4, 2)) + CLng(Mid(strData, 6, 2)) = CLng(Mid(strData, 8, 2)) Then
      MsgBox strData
    End If
  End If
End Sub

総当りなので、かなり遅いと思います。
そのかわりに、式が変更になっても修正が簡単です。
(わかりやすいように文字列で処理しています)


2.ab, c, fg だけ総当り、de, hi は式から計算

Sub Macro2()
  Dim ab As Long, c As Long, de As Long, fg As Long, hi As Long
  Dim p(1 To 9) As Long
  Dim flags(1 To 9) As Boolean
  Dim j As Long

  For ab = 12 To 98
    For c = 1 To 9
      For fg = 12 To 98
        de = ab * c
        hi = de + fg
        If de <= 98 And hi <= 98 Then
          p(1) = ab \ 10
          p(2) = ab Mod 10
          p(3) = c
          p(4) = de \ 10
          p(5) = de Mod 10
          p(6) = fg \ 10
          p(7) = fg Mod 10
          p(8) = hi \ 10
          p(9) = hi Mod 10
          For j = LBound(flags()) To UBound(flags())
            flags(j) = False
          Next
          For j = LBound(p()) To UBound(p())
            If 1 <= p(j) And p(j) <= 9 Then
              If flags(p(j)) Then Exit For
              flags(p(j)) = True
            Else
              Exit For
            End If
          Next
          If j > UBound(p()) Then
            MsgBox p(1) & p(2) & p(3) & p(4) & p(5) & p(6) & p(7) & p(8) & p(9)
          End If
        End If
      Next
    Next
  Next
End Sub


>#このロジックでは組み合わせは1通りしか探せなかったけど、正解かなぁ(??)

私も1通りなので、多分正解かなぁ
重複判断って面倒くさいですね^^;

横レスごめんね。実は昨日から考えてたの^^;

ではではぁ
 ───────────────────────────────────────  ■題名 : Re:計算式をつくるには  ■名前 : 禰宜 <mune109@hotmail.com>  ■日付 : 02/9/11(水) 23:00  -------------------------------------------------------------------------
   失礼いたします。
こんな感じでもOKかな?

まず積の部分(上5桁)を条件に処理し、
その後、和の部分(下4桁)を処理するというのが
早く処理する第一歩かもしれません。

Sub Part_1()
Dim i As Long
Dim t As Integer
Dim Flag_1 As Boolean

For i = 12345 To 98765
If InStr(CStr(i), "0") = 0 Then
 If Val(Left(i, 2)) * Val(Mid(i, 3, 1)) = Val(Mid(i, 4, 2)) Then
  Flag_1 = True
  For t = 1 To 9
   If InStr(CStr(i), t) <> InStrRev(CStr(i), t) Then
   Flag_1 = False
   Exit For
   End If
  Next
  If Flag_1 = True Then Call Part_2(i)
  End If
 End If
Next

End Sub

Private Sub Part_2(k As Long)
Dim m As Long
Dim n As Integer
Dim Flag_2 As Boolean

For m = k * 10000 + 1234 To k * 10000 + 9876
If InStr(CStr(m), "0") = 0 Then
 If Val(Right(k, 2)) + Val(Mid(m, 6, 2)) = Val(Right(m, 2)) Then
  Flag_2 = True
  For n = 1 To 9
   If InStr(CStr(m), n) <> InStrRev(CStr(m), n) Then
   Flag_2 = False
   Exit For
   End If
  Next
  If Flag_2 = True Then MsgBox CStr(m)
  End If
 End If
Next

End Sub


[Part_1]と[Part_2]があり、Part_2はPrivateです。

Part_1を実行するとOKです。
他の方と同様に答えは1つでした。

では。
 ───────────────────────────────────────  ■題名 : Re:計算式をつくるには  ■名前 : おらんじゅ  ■日付 : 02/9/12(木) 21:08  -------------------------------------------------------------------------
   こうちゃんさん、jujuさん、禰宜さん、こんなに早いご回答感謝です!
私は初心者なもので、それぞれのマクロを理解するのに時間がかかってしまいまして・・・。
勉強になりました!どうもありがとうございました!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━    通常モードに戻る  ┃  INDEX  ┃  ≪前へ  │  次へ≫    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                                 Page 69