AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Searching diagonally?

 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 12:06 pm    Post subject: Searching diagonally? Reply with quote

I'm curious the best way to search a group of letters diagonally, like in a word search puzzle. Obviously it is easy to search forwards and backwards by simply reversing a string, but diagonally seems much harder to figure out.

Assume this is the puzzle:
Code:
A B G
D O F
D H I

And I want to find the word "DOG" and return the starting and end positions. D would be (3,1) and G would be (1,3).

I want to create a function that does not assume that forwards is the only option nor that all puzzles are only 3 characters wide/tall, so it should also work with this puzzle:
Code:
A B C D
E G G H
I J O L
M N O D
etc...

Would anyone like to help me out with this? This type of thing is probably easier than it looks; but for me, I can't seem to wrap my head around it.

Thanks for any help!

Adam
Back to top
View user's profile Send private message
any0ne
Guest





PostPosted: Wed Mar 10, 2010 2:35 pm    Post subject: Reply with quote

We AHKers call that a Laszlo challenge!! Very Happy
Back to top
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 2:37 pm    Post subject: Reply with quote

any0ne wrote:
We AHKers call that a Laszlo challenge!! Very Happy


Very Happy hehe, I also just realized that searching up and down might be just as hard. That should be considered as well. Hmm....
Back to top
View user's profile Send private message
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 2:43 pm    Post subject: Reply with quote

I figured out a way to "rotate" the puzzle to allow searching up and down:

Code:
Letters=
(
R H H V M A Y Q C U Q D P R H B K D
D P X G H S V O D W C P M L U G L K
Z Q S I X S G O U I C K O R B K K X
W K Z H T V P N V J P Q L N G D M A
W X A S I R U S Y R X E C I V T B Z
A F E R E L U R D J Z G R U V U V Y
O J K E C V A B R Y M S O B O Z F B
I Y H N Y A E C T K A S N K Z V H Q
T C Z I O E D M I M J J C Q H S O I
L S I I Z I W E L M T O F X B C Z U
S Q U O H N T F S E O P O Z Z X P S
T O C H D Z R A S S E C H D S Y W W
C H A G R I N N X I A P D L K D G G
U O M V Z C U J U A X R J F T N B R
M E N L M S S V L U L W G X A C H L
K D M N W S T G D Z L E B U Z G C L
D X X B S K I L L F V I R B U U W F
D V C P R C D I V E R S I O N K U Z
)

StringReplace,Letters,Letters,%A_Space%,,All
   
Loop,Parse,Letters,`n
   {
      Loop,Parse,A_LoopField
         var%A_Index% := var%A_Index% A_LoopField
   }
   
Letters_R := var1 "`n" var2 "`n" var3 "`n" var4 "`n" var5 "`n" var6 "`n" var7 "`n" var8 "`n" var9 "`n" var10 "`n" var11 "`n" var12 "`n" var13 "`n" var14 "`n" var15 "`n" var16 "`n" var17 "`n" var18

MsgBox % Letters_R
Back to top
View user's profile Send private message
answer4u
Guest





PostPosted: Wed Mar 10, 2010 3:03 pm    Post subject: Reply with quote

Perhaps an oversimplified answer, but if you break the data down into a 2D Grid/Array, then it becomes sheer mathematics on extracting the letters in a diagonal format to check for words. I would recommend AHKL for its object support here.
Back to top
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 3:12 pm    Post subject: Reply with quote

answer4u wrote:
Perhaps an oversimplified answer, but if you break the data down into a 2D Grid/Array, then it becomes sheer mathematics on extracting the letters in a diagonal format to check for words. I would recommend AHKL for its object support here.


Yea, I thought about AHKL too, but its figuring out the mathematics that is confusing too... Sad
Back to top
View user's profile Send private message
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 3:51 pm    Post subject: Reply with quote

Well, this definetly is not very pretty, but I've figured out a way to rearrange the letters into diagonal lines:

Code:
#SingleInstance,Force

Letters=
(
R H H V M A Y Q C U Q D P R H B K D
D P X G H S V O D W C P M L U G L K
Z Q S I X S G O U I C K O R B K K X
W K Z H T V P N V J P Q L N G D M A
W X A S I R U S Y R X E C I V T B Z
A F E R E L U R D J Z G R U V U V Y
O J K E C V A B R Y M S O B O Z F B
I Y H N Y A E C T K A S N K Z V H Q
T C Z I O E D M I M J J C Q H S O I
L S I I Z I W E L M T O F X B C Z U
S Q U O H N T F S E O P O Z Z X P S
T O C H D Z R A S S E C H D S Y W W
C H A G R I N N X I A P D L K D G G
U O M V Z C U J U A X R J F T N B R
M E N L M S S V L U L W G X A C H L
K D M N W S T G D Z L E B U Z G C L
D X X B S K I L L F V I R B U U W F
D V C P R C D I V E R S I O N K U Z
)

StringReplace,Letters,Letters,%A_Space%,,All

Loop,Parse,Letters,`n
   {
      space =
      Loop % A_Index - 1
         space := space A_Tab
      B_Letters := B_Letters space A_LoopField "`n"
   }

StringTrimRight,B_Letters,B_Letters,1

Loop,Parse,B_Letters,`n
   {
      Loop,Parse,A_LoopField
         var%A_Index% := var%A_Index% A_LoopField ; or var%A_Index% := A_LoopField var%A_Index%
   }

Loop,35
   Letters_D := Letters_D var%A_Index% "`n"

StringReplace,Letters_D,Letters_D,%A_Tab%,,All

StringTrimRight,Letters_D,Letters_D,1

Letters_D2 := AddSpaces(Letters_D)
   
msgbox '%Letters_D2%'

Return

AddSpaces(x) {
   return RegExReplace(x, "(?(?<=\.)(*COMMIT)(*FAIL))\w(?=(\w{1})+(\W|$))", "$0 ")
}
Back to top
View user's profile Send private message
answer4u
Guest





PostPosted: Wed Mar 10, 2010 3:57 pm    Post subject: Reply with quote

Quick Example:
Code:
Letters=
(
R H H V M A Y Q C U Q D P R H B K D
D P X G H S V O D W C P M L U G L K
Z Q S I X S G O U I C K O R B K K X
W K Z H T V P N V J P Q L N G D M A
W X A S I R U S Y R X E C I V T B Z
A F E R E L U R D J Z G R U V U V Y
O J K E C V A B R Y M S O B O Z F B
I Y H N Y A E C T K A S N K Z V H Q
T C Z I O E D M I M J J C Q H S O I
L S I I Z I W E L M T O F X B C Z U
S Q U O H N T F S E O P O Z Z X P S
T O C H D Z R A S S E C H D S Y W W
C H A G R I N N X I A P D L K D G G
U O M V Z C U J U A X R J F T N B R
M E N L M S S V L U L W G X A C H L
K D M N W S T G D Z L E B U Z G C L
D X X B S K I L L F V I R B U U W F
D V C P R C D I V E R S I O N K U Z
)

table := Grid( letters )
MsgBox, % table.diagonalup( 16 ) ; param is row number
Return


Grid( data ) {
   obj := object( "diagonalup", "diagonalup" )
   array := object( "base", obj )
   Loop, Parse, data, `n, `r
   {
      n := A_Index
      Loop, Parse, A_LoopField, %A_Space%
         array[ n, A_Index ] := A_LoopField
   }
   Return, array
}
DiagonalUp( obj, row ) {
   If ( row > obj._MaxIndex() )
      Return, "ERROR"
   Loop, %row%
      string .= obj[ row-A_Index+1, A_Index ]
   Return, string
}
Back to top
da_boogie_man
Guest





PostPosted: Wed Mar 10, 2010 5:17 pm    Post subject: Reply with quote

What if you were to assign each letter to a variable "array"?

var_%row%_%col%

Then you would have your word list:

wrdList =
(
top
dog
banana
auto
hot
key
rocks
)

"Loop, Parse" the list and search for the first letter, when it finds a match use your array to search for the 2nd letter in the surrounding letters. If it's found the 3rd letter should be in the same direction.

Dang it! Now I have to try this! Laughing

DBM
Back to top
Guest






PostPosted: Wed Mar 10, 2010 6:33 pm    Post subject: Reply with quote

instead of searching surroundings
shouldnt it be easier to produce 4 list? (might need some brain to produce the equation)
example:
Code:

a b c
d e f
g h i

can produce:
1. abcdefg
2. adgbehcfi
3. adbgechfi
4. cbfaeidhg
and then search the string
if found, then check position
Back to top
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 6:35 pm    Post subject: Reply with quote

Anonymous wrote:
instead of searching surroundings
shouldnt it be easier to produce 4 list? (might need some brain to produce the equation)
example:
Code:

a b c
d e f
g h i

can produce:
1. abcdefg
2. adgbehcfi
3. adbgechfi
4. cbfaeidhg
and then search the string
if found, then check position


This is what I did (partially) in my example.
Back to top
View user's profile Send private message
adamrgolf



Joined: 28 Dec 2006
Posts: 440

PostPosted: Wed Mar 10, 2010 7:02 pm    Post subject: Reply with quote

Here is an example that does not require generating/rearranging multiple lists, I'm sure this can be shortened dramatically, but it works...

Code:
#SingleInstance,Force

Letters=
(
R H H V M A Y Q C U Q D P R H B K D
D P X G H S V O D W C P M L U G L K
Z Q S I X S G O U I C K O R B K K X
W K Z H T V P N V J P Q L N G D M A
W X A S I R U S Y R X E C I V T B Z
A F E R E L U R D J Z G R U V U V Y
O J K E C V A B R Y M S O B O Z F B
I Y H N Y A E C T K A S N K Z V H Q
T C Z I O E D M I M J J C Q H S O I
L S I I Z I W E L M T O F X B C Z U
S Q U O H N T F S E O P O Z Z X P S
T O C H D Z R A S S E C H D S Y W W
C H A G R I N N X I A P D L K D G G
U O M V Z C U J U A X R J F T N B R
M E N L M S S V L U L W G X A C H L
K D M N W S T G D Z L E B U Z G C L
D X X B S K I L L F V I R B U U W F
D V C P R C D I V E R S I O N K U Z
)

StringReplace,Letters,Letters,%A_Space%,,All
StringReplace,Letters,Letters,`n,,All

Word := "DIVERSION"

pos := SearchNorm(Word)
If InStr(pos,"0`,0")
   pos := SearchNorm(Flip(Word))
If InStr(pos,"0`,0")
   pos := SearchDiag(Word)
If InStr(pos,"0`,0")
   pos := SearchDiag(Flip(Word))

msgbox %Word% found at: %pos%

Word := "GRASS"

pos := SearchNorm(Word)
If InStr(pos,"0`,0")
   pos := SearchNorm(Flip(Word))
If InStr(pos,"0`,0")
   pos := SearchDiag(Word)
If InStr(pos,"0`,0")
   pos := SearchDiag(Flip(Word))

msgbox %Word% found at: %pos%

Return

SearchNorm(Word)   {
   Global Letters
   fp := RegExMatch(Letters,Word)
   If fp=0
      pos := "(0`,0)"
   If (fp <= 18) AND (fp > 0)
      pos := "(1," fp ")"
   if fp > 18
      {
         bp := fp
         Loop,
            {
               b_index := A_Index + 1
               bp := bp - 18
               If bp <=18
                  Break
            }                     
         Pos :="(" b_index ","  Mod(fp,18) ")"
      }
   If ! InStr(pos,"0`,0")
      Return pos
   String=
   Loop,parse,Word
      String := String A_LoopField "\w{17}"
   
   StringTrimRight,String,String,6
   
   fp := RegExMatch(Letters,String)
   
   If fp=0
      pos := "(0`,0)"
   If (fp <= 18) AND (fp > 0)
      pos := "(1," fp ")"
   if fp > 18
      {
         bp := fp
         Loop,
            {
               b_index := A_Index + 1
               bp := bp - 18
               If bp <=18
                  Break
            }                     
         Pos :="(" b_index ","  Mod(fp,18) ")"
      }
   If ! InStr(pos,"0`,0")
      Return pos
   Return pos
}

SearchDiag(Word)   {
   Global Letters
   String=
   Loop,parse,Word
      String := String A_LoopField "\w{18}"
   
   StringTrimRight,String,String,6
   
   fp := RegExMatch(Letters,String)
   
   If fp=0
      pos := "(0`,0)"
   If (fp <= 18) AND (fp > 0)
      pos := "(1," fp ")"
   if fp > 18
      {
         bp := fp
         Loop,
            {
               b_index := A_Index + 1
               bp := bp - 18
               If bp <=18
                  Break
            }                     
         Pos :="(" b_index ","  Mod(fp,18) ")"
      }
   If ! InStr(pos,"0`,0")
      Return pos   
   String=
   Loop,parse,Word
      String := String A_LoopField "\w{16}"
   
   StringTrimRight,String,String,6
   
   fp := RegExMatch(Letters,String)
   
   If fp=0
      pos := "(0`,0)"
   If (fp <= 18) AND (fp > 0)
      pos := "(1," fp ")"
   if fp > 18
      {
         bp := fp
         Loop,
            {
               b_index := A_Index + 1
               bp := bp - 18
               If bp <=18
                  Break
            }                     
         Pos :="(" b_index ","  Mod(fp,18) ")"
      }
   If ! InStr(pos,"0`,0")
      Return pos
   Return pos
}

Flip( Str) {
 Loop, Parse, Str
  nStr=%A_LoopField%%nStr%
Return nStr
}
Back to top
View user's profile Send private message
jethrow



Joined: 24 May 2009
Posts: 1907
Location: Iowa, USA

PostPosted: Thu Mar 11, 2010 3:50 am    Post subject: Reply with quote

So I spent way to long trying this, but here's an example bridging off a previous post - where the variable "letters" is the same as in the previous posts ( requires AHKL ):
Code:
table := Grid( letters )
MsgBox, 0, % "Row, Col", % table.word( "sunset" )
MsgBox, 0, % "Row, Col", % table.word( "DIVERSION" )
Return


Grid( data ) { ; separates data into 2D Array/Object
   obj := object(   "row",            "row"
               ,   "column",         "column"
               ,   "diagonal",         "diagonal"
               ,   "diagonalcoord",   "diagonalcoord"
               ,   "word",            "word"   )
   array := object( "base", obj )
   Loop, Parse, data, `n, `r
   {
      n := A_Index
      Loop, Parse, A_LoopField, %A_Space%
         array[ n, A_Index ] := A_LoopField
   }
   array.rows := array._MaxIndex(), array.columns := array[1]._MaxIndex()
   array.diagonals := array.rows+array.columns-1
   Return, array
}
Row( obj, item, rev=0 ) { ; returns row string
   Loop, % obj.columns
      string .= rev ? obj[ item, obj.columns-A_Index+1 ] : obj[ item, A_Index ]
   Return, string
}
Column( obj, item, rev=0 ) { ; returns columns string
   Loop, % obj.rows
      string .= rev ? obj[ obj.rows-A_Index+1, item ] : obj[ A_Index, item ]
   Return, string
}
Diagonal( obj, item ) { ; gets a diagonals string of letters
   If ( item > obj.diagonals )
      Return, "ERROR"
   Loop, % obj.diagonals
      string .= item>0 ? obj[ item-A_Index+1, A_Index ] : obj[ A_Index, obj.columns+item+A_Index ]
   Return, string
}
DiagonalCoord( obj, item, pos ) { ; returns the "R,C" position of a position in a diagonal string
   If ( item > obj.diagonals )
      Return, "ERROR"
   If ( item>0 )
      If ( item <= obj.rows )
         row := item-pos+1, col := pos
      Else
         row := obj.rows-pos+1, col := pos + ( item-obj.rows )
   Else
      If ( item >= -1*obj.columns )
         row := pos, col := obj.columns+item+pos
      Else
         row := pos + ( -1*obj.columns-item ), col := pos
   Return, row>0 && row<=obj.rows && col>0 && col<=obj.columns
            ?   row "," col : "Invalid Parameters"
}
Word( obj, word ) { ; searches for a word
   If ( word = "" )
      Return, "No Word"

   Loop, % obj.rows ; horizontal search
      If pos := InStr( obj.row( A_Index ), word )
         Return, A_Index "," pos
      Else If pos := InStr( obj.row( A_Index, "Reverse" ), word )
         Return, A_Index "," obj.columns-pos+1
         
   Loop, % obj.columns ; vertical search
      If pos := InStr( obj.column( A_Index ), word )
         Return, pos "," A_Index
      Else If pos := InStr( obj.column( A_Index, "Reverse" ), word )
         Return, obj.rows-pos+1 "," A_Index
         
   While( !item && A_Index<=obj.diagonals ) { ; diagonal search
      string := obj.diagonal( A_Index )
      string2 := obj.diagonal( -1 * A_Index )
      If pos := InStr( string, word )
         item := A_Index
      Else If pos := InStr( Flip(string), word )
         item := A_Index, pos := StrLen(string)-pos+1
      Else If pos := InStr( string2, word )
         item := -1 * A_Index
      Else If pos := InStr( Flip(string2), word )
         item := -1 * A_Index, pos := StrLen(string)-pos+1
   }
   Return, item ? obj.diagonalCoord( item, pos ) : "N\A"
}
Flip(in) { ; http://www.autohotkey.com/forum/topic46040.html&start=5
    VarSetCapacity(out, n:=StrLen(in))
    Loop %n%
        out .= SubStr(in, n--, 1)
    return out
}

Also, if anyone cares, the numbering of the diagonal strings is like this:
Code:
Going up/right         Going down/right
1                     -4 -3 -2 -1
2                     -5
3                     -6
4 5 6 7               -7

_________________
Very Happy - in case I forgot to smile
Basic Webpage Controls
COM Object Reference
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group