2D Array to display characters

Hi All,

I have a series of number which indicates the coordinates
where 0104 indicates X-coord = 01 and Y-coord = 04 and i want characters to form up in accordance to the coordinates given.
Can any expert give me an example of 2D array code using csh or awk or perl such that the code can display the characters below ?

EG:
Inputfile:
0101 A
0102 B
0103 C
0104 D
0201 E
0202 F
0203 G
0204 H
0301 I
0302 J
0303 K
0304 L

04  D   H   L 
03  C   G   K
02  B   F   J
01  A   E   I  
   01  02  03

This way:

awk '{
X[$2]=substr($1,1,2)
Y[$2]=substr($1,3)
}
END {
for ( y in Y)
   for ( x in X )
      if ( x == y  )
        {
        dx=sprintf("%d",X[x])
        dy=sprintf("%d",Y[y])
        if ( dx >= max_x )
           max_x=dx
        if ( dy >= max_y )
           max_y=dy
        f[dx,dy]=x 
        }
for (i=max_y;i>=1;i--)
    {
    printf("%2d",i)
    for (j=1;j<=max_x;j++)
       printf(" %2s",f[j,i])
    printf("\n")
    }
printf("   ")
for (j=1;j<=max_x;j++)
   printf("%2d ",j)
print
} ' file
 4  D  H  L
 3  C  G  K
 2  B  F  J
 1  A  E  I
    1  2  3 

Hi Klashxx,

Your code is really cool. Thks , it works up till a 9x9 matrix.
However, I tried the code with x-coordinates 10 and above and it doesn't work. Can you help ?

EG:
Inputfile:
0101 A
0102 B
0103 C
0104 D
0201 E
0202 F
0203 G
0204 H
0301 I
0302 J
0303 K
0304 L
1001 M
1002 N

Ok, it was a conversion problem, so:

> cat file
0101 A
0102 B
0103 C
0104 D
0201 E
0202 F
0203 G
0204 H
0301 I
0302 J
0303 K
0302 L
0903 U
1001 M
1002 N
1104 �
1504 F
2005 N
>awk '{
X[$2]=substr($1,1,2)
Y[$2]=substr($1,3)
}
END {
for ( y in Y)
   for ( x in X )
      if ( x == y  )
        {
        dx=X[x]+0
        dy=Y[y]+0
        if ( dx >= max_x )
           max_x=dx
        if ( dy >= max_y )
           max_y=dy
        f[dx,dy]=x 
        }
for (i=max_y;i>=1;i--)
    {
    printf("%.2d",i)
    for (j=1;j<=max_x;j++)
       printf(" %2s",f[j,i])
    printf("\n")
    }
printf("   ")
for (j=1;j<=max_x;j++)
   printf("%.2d ",j)
print
} ' file
05                                                           N
04  D  H                          �           F               
03  C  G  K                 U                                 
02  B     L                                                   
01  A  E  I                    M                              
   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20  

Bye

Hi Klashxx,

Strange, i tried to use yr modified code but some strange characters appear at the end of output in blue. Can you give some advice on that

$ cat input1
0101 A
0102 B
0103 C
0104 D
0201 E
0202 F
0203 G
0204 H
0301 I
0302 J
0303 K
0302 L
0801 Z
0903 U
1001 M
1002 N

$ awk -f 2d_array input1
04  D  H
03  C  G  K                 U
02  B  F  L                    N
01  A  E  I              Z     M
   01 02 03 04 05 06 07 08 09 10 1002 N

Hi , change last print for printf("\n")

Hi Klashxx,

Thks a million!!!!. It works!!
Thats real cool!!.
But i am a beginner in awk, can you explain your code such that i can comprehend better. Especially the looping part, which seems confusing to me.

Here u have the new commented version (new feature added):

> cat file
0101 A
0102 B
0103 C
0104 D
0201 E
0202 F
0203 G
0204 H
0301 I
0302 J
0303 K
0302 L
0903 U
1001 M
1002 N
1610 U
1104 �
1504 F
2005 N
>awk '{
# Associative arrays to store the coordinates of each element
# the source file could have duplicates so we add the Number of Record (NR)
# variable to $2 in order to get uniques items. 
X[$2""NR]=substr($1,1,2) 
Y[$2""NR]=substr($1,3)
}
END {
for ( y in Y)                   #BEGIN First loop:go through Y  
   for ( x in X )               #BEGIN Second loop:for each item of Y go through X 
      if ( x == y  )            #BEGIN if
        {                       #if both  elements of X and Y have the same index ($2+NR in the source file)
        dx=X[x]+0               #Store x value and add 0 to convert it to integer
        dy=Y[y]+0               #Store y value and add 0 to convert it to integer
        if ( dx >= max_x )     
           max_x=dx             #Is this the maximum x value ?
        if ( dy >= max_y )
           max_y=dy             #Is this the maximum y value ?
        f[dx,dy]=substr(x,1,1)  #Store the result in a 2D array and get rid of the NR part  
        break                   #Cause each element is unique ,dont need to look for another "x==y" so break second loop
        }                       #END if
                                #END Second loop
                                #END First loop
 
# SHOW RESULTS (i ll leave the presentation code for you)        
        
for (y=max_y;y>=1;y--)          #BEGIN coordinate y loop
    {
    printf("%.2d|",y)
    for (x=1;x<=max_x;x++)      #BEGIN coordinate x loop
       printf(" %2s|",f[x,y])   #END coordinate x loop --> Just print in the correct place the item. 
    printf("\n")
    for (x=1;x<max_x+2;x++)
       printf("----")
    printf("\n")
    }                           #END coordinate y loop         
printf("  ")
for (x=1;x<=max_x;x++)
   printf("|%.2d ",x)
printf("|\n")
} ' file
10|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |  U|   |   |   |   |
------------------------------------------------------------------------------------
09|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
08|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
07|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
06|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
05|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |  N|
------------------------------------------------------------------------------------
04|  D|  H|   |   |   |   |   |   |   |   |  �|   |   |   |  F|   |   |   |   |   |
------------------------------------------------------------------------------------
03|  C|  G|  K|   |   |   |   |   |  U|   |   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
02|  B|  F|  J|   |   |   |   |   |   |  N|   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
01|  A|  E|  I|   |   |   |   |   |   |  M|   |   |   |   |   |   |   |   |   |   |
------------------------------------------------------------------------------------
  |01 |02 |03 |04 |05 |06 |07 |08 |09 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |

Cheers

Wow Klashxx!! That code of your was spectacular !!
And thanks for the comprehensive explanation.
I have definitely learnt alot out of this.

Just a couple of question:
1) If the character to be displayed sometimes contain a maximum of 2 characters (number of characters will not exceed 2), how can you modify your code to suit this requirement ?
EG:
0101 AA
0102 B
0103 CD
0104 D
0201 EG
0202 F
0203 G
0204 HH

2) If the coordinates is not displayed in the input file , eg 0202 is not provided here, can you allow your code to print a minus character " - " when this situation arise.

EG:
0101 A
0102 B
0201 C

Expected output:

02  B  -
01  A  C
   01 02 

This way:

> cat file
0101 A
0102 BH
0103 C
0104 D
0201 E
0202 F
0203 G
0204 HG
0301 I
0302 LZ
0303 K
0903 U
1001 M
1002 NX
1610 U
1405 GH
1104 �
1504 F
1902 LL
2005 N
>awk '{
# Associative arrays to store the coordinates of each element
# the source file could have duplicates so we add the Number of Record (NR)
# variable to $2 in order to get uniques items. 
X[$2""NR]=substr($1,1,2) 
Y[$2""NR]=substr($1,3)
}
END {
for ( y in Y)                   #BEGIN First loop:go through Y  
   for ( x in X )               #BEGIN Second loop:for each item of Y go through X 
      if ( x == y  )            #BEGIN if
        {                       #if both  elements of X and Y have the same index ($2+NR in the source file)
        dx=X[x]+0               #Store x value and add 0 to convert it to integer
        dy=Y[y]+0               #Store y value and add 0 to convert it to integer
        if ( dx >= max_x )     
           max_x=dx             #Is this the maximum x value ?
        if ( dy >= max_y )
           max_y=dy             #Is this the maximum y value ?
        gsub(/[0-9]+$/,"",x)      #get rid of the NR part
        f[dx,dy]=x              #Store the result in a 2D array
        break                   #Cause each element is unique ,dont need to look for another "x==y" so break second loop
        }                       #END if
                                #END Second loop
                                #END First loop
 
# SHOW RESULTS (i ll leave the presentation code for you)        
        
for (y=max_y;y>=1;y--)          #BEGIN coordinate y loop
    {
    printf("%.2d",y)
    for (x=1;x<=max_x;x++)      #BEGIN coordinate x loop
       {
       if ( f[x,y] == "" )      #Coordinates not displayed (null value in array)
           printf("  -")
       else
          printf(" %2s",f[x,y])
       }                        #END coordinate x loop --> Just print in the correct place the item. 
    printf("\n")
    }                           #END coordinate y loop         
printf("   ")
for (x=1;x<=max_x;x++)
   printf("%.2d ",x)
printf("\n")
} ' file
10  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  U  -  -  -  -
09  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
08  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
07  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
06  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
05  -  -  -  -  -  -  -  -  -  -  -  -  - GH  -  -  -  -  -  N
04  D HG  -  -  -  -  -  -  -  -  �  -  -  -  F  -  -  -  -  -
03  C  G  K  -  -  -  -  -  U  -  -  -  -  -  -  -  -  -  -  -
02 BH  F LZ  -  -  -  -  -  - NX  -  -  -  -  -  -  -  - LL  -
01  A  E  I  -  -  -  -  -  -  M  -  -  -  -  -  -  -  -  -  -
   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

A final optimization , i notice that associative arrays ar useless here:

>awk '{
x=substr($1,1,2)+0
y=substr($1,3)+0
if ( x >= max_x )     
    max_x=x             #Is this the maximum x value ?
if ( y >= max_y )
   max_y=y             #Is this the maximum y value ?
f[x,y]=$2
}
END {
# SHOW RESULTS (i ll leave the presentation code for you)        
        
for (y=max_y;y>=1;y--)          #BEGIN coordinate y loop
    {
    printf("%.2d",y)
    for (x=1;x<=max_x;x++)      #BEGIN coordinate x loop
       {
       if ( f[x,y] == "" )      #Coordinates not displayed (null value in array)
           printf("  -")
       else
          printf(" %2s",f[x,y])
       }                        #END coordinate x loop --> Just print in the correct place the item. 
    printf("\n")
    }                           #END coordinate y loop         
printf("   ")
for (x=1;x<=max_x;x++)
   printf("%.2d ",x)
printf("\n")
} ' file
10  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  U  -  -  -  -
09  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
08  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
07  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
06  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
05  -  -  -  -  -  -  -  -  -  -  -  -  - GH  -  -  -  -  -  N
04  D HG  -  -  -  -  -  -  -  - �  -  -  -  F  -  -  -  -  -
03  C  G  K  -  -  -  -  -  U  -  -  -  -  -  -  -  -  -  -  -
02 BH  F LZ  -  -  -  -  -  - NX  -  -  -  -  -  -  -  - LL  -
01  A  E  I  -  -  -  -  -  -  M  -  -  -  -  -  -  -  -  -  -
   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

Hi Klashxx,

Thnks !!! It really looks fabulous now .
I think it works now and codes are more concise after the optimisation.

Jus a question, what's the purpose of adding the " +0 " at the end of the codes. Is x and y arrays now ?

x=substr($1,1,2)+0
y=substr($1,3)+0

What if no " +0 " is added ? What will happen ?

You need it to force the conversion of the string that results of the substr function to a integer.
From The AWK Manual - Data Type Summary:

"The awk language defines comparisons as being done numerically if both operands are numeric, or if one is numeric and the other is a numeric string. Otherwise one or both operands are converted to strings and a string comparison is performed"

Remove +0 and look what happens.

Hi Klashxx,

Thanks a million for for the guidance!!
I have definitely acquire alot of knowledge from you.:b::wink:
:smiley:

Hi Klashx,

Now i would like to perform the reverse function, that is the input is in a table form but i would like the ouput to be in a coordinate form.
Can you help ?

                                                        
04  D  H                                     
03  C  G  K                                             
02  B     L                                                   
01  A  E  I                                               
   01 02 03 04

Output:
0101 A
0102 B
0103 C
0404 D
0201 E
0202 -
0203 G
0204 H
0301 I
0302 L
0303 K
0304 -
0401 -
0402 -
0403 -
0404 -

duplicated post

Hi Raynon, supposing that FieldSeparator is 2 blanks:

> cat file
04  D  H     
03  C  G  K   
02  B     L   
01  A  E  I   
   01 02 03 04
sed -ne 's/  /,/g;1!G;h;$p' file |awk 'NR>1{
gsub(/ */,"")
for (i=2;i<=NF;i++)
   {
   if ( $i == "" )
   $i="-"
   printf("%02d%02d %s\n",i-1,NR-1,$i)
   }
}' FS=','|sort -k1
0101 A
0102 B
0103 C
0104 D
0201 E
0202 -
0203 G
0204 H
0301 I
0302 L
0303 K
0304 -
0401 -
0402 -
0403 -
0404 -

Cheers