作者: Hiroshi Shinohara
日時: 2003/10/24(00:18)
  前回の続きです。  エクセルの列番号関係では、
    ・アルファベット "A"-"Z"を 数字 1-26に 変換する
    ・数字 1-26 をアルファベット "A"-"Z"に 変換する
のが、基本処理ですね。

  Iconで、この変換を行うのに どういうやり方があるか を考えてみました。

  まず、"A"-"Z" -> 1-26です。
-----^ A2N.ICN ( date:03-10-23 time:23:53 ) ----------------<cut here
####################
# アルファベット -> 数 変換
####################
# 文字 "A"-"Z" を 数 1-26へ変換
# a2n.icn Rev.1.1 2003/10/23 風つかい
# This file is in the public domain.

procedure main()
  L := [a2n1,a2n2,a2n3,a2n4,a2n5]     # 変換 procedureの list

  write("A-Zを 1-26へ変換")
  every proc1 := !L do {              # 変換 procedureを順に取り出して
    writes(image(proc1)[11:0],":")    # procedure名を出力
                                      # image例 "procedure a2n1"の 11文字以降
    every writes(" ",proc1(!&ucase))  # A-Zの変換出力を順に書き出す
    write()              # ↑'AB..Z'の文字セット から順に取り出す
  }
end

##  1 ##############
# 文字 -> 数 変換関数を使用
####################
procedure a2n1(s)
  return ord(s) -ord("A") +1  # アルファベット A-Zはコード上で昇順に
end                           # 連続配置されている前提

##  2 ##############
# "AB..Z" の文字列を走査し、sの位置を調べる
####################
procedure a2n2(s)
  return &ucase ? upto(s)     # &ucase中の sの位置を返す
end                           # 文字セット'AB..Z'は、文字列"AB..Z"と見なされる

##  3 ##############
# 文字置換関数を使う
####################
procedure a2n3(s)
    # ↓置換した結果が元の文字と変わっていれば、置換成功
  (s ~==:= map(s,"ABCDEFGHIJ","0123456789")) |               # いずれかが成功
  (s ~==:= map(s,"KLMNOPQRST","0123456789"),s := "1" || s) | # するハズ。
  (s ~==:= map(s,"UVWXYZ",    "012345")    ,s := "2" || s)   # 

  return integer(s) +1            # integer:整数へ変換 "12" -> 12
end
# ~==:= は、左辺と右辺の文字列が異なっていれば、左辺へ右辺を代入する。
# A-Zでは面倒だが、A-J -> 0-9 位の変換には 手軽。
# integer(map(s,"ABCDEFGHIJ","0123456789")) で、見た目に分かりやすい。

##  4 ##############
# tableを使う
####################
procedure a2n4(s)
  static Ta2n                 # 次回に呼ばれた時まで記憶
  initial {                   # 初回だけ実行
    Ta2n := table()           # table生成
    n := 0                    # 文字の番号
    every ss := !&ucase       # 'AB..Z'の文字セット から順に取り出す
     do Ta2n[ss] := (n +:= 1) # tableへ登録 例: key:"A" -> value:1
  }
  return Ta2n[s]              # table参照結果
end

##  5 ##############
# 36進数とみなして、数へ変換し補正する
####################
# 36rAは、36進のA (10進の 10)を表す。
# Iconでの数表記には、10進表記と基数表記がある。
# 基数は 2〜36で、数は 0〜9,A-Zを使用。r,A-Zは大文字でも小文字でも構わない。
procedure a2n5(s)
  return integer("36r" || s) -9 # integerは整数化関数  少数点以下切り捨て
end                             # および 10進数表記、基数表記を 数に変換
                                # "36rA" -> 10 .. "36rZ" -> 35
# BIPL(Icon基本ライブラリ)の convert.icn中の inbase10では こんな風なやり方で、
# 基数表記 -> 数へ変換している。
-----$ A2N.ICN ( lines:74 words:261 ) ----------------------<cut here

  結果はこうなります。どれも同じ結果で 面白味は無いですが。
-----^ A2N.1 ( date:03-10-23 time:23:55 ) ------------------<cut here
A-Zを 1-26へ変換
a2n1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
a2n2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
a2n3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
a2n4: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
a2n5: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
-----$ A2N.1 ( lines:6 words:137 ) -------------------------<cut here

  次は、1-26 -> "A"-"Z"です。
-----^ N2A.ICN ( date:03-10-23 time:23:55 ) ----------------<cut here
####################
# 数 -> アルファベット 変換
####################
# 数 1-26 を "A"-"Z" へ変換
# n2a.icn Rev.1.1 2003/10/23 風つかい
# This file is in the public domain.

procedure main()
  L := [n2a1,n2a2,n2a3,n2a4]          # 変換 procedureの list

  write("1-26を A-Zへ変換")
  every proc1 := !L do {              # 変換 procedureを順に取り出して
    writes(image(proc1)[11:0],":")    # procedure名を出力
                                      # image例 "procedure n2a1"の 11文字以降
    every writes(" ",proc1(seq() \26))   # 1-26の変換出力を順に書き出す
    write()              # ↑1 から順に数字を発生する関数(generator)
  }                      # \26は発生数を 26個に限定
end

##  1 ##############
# 数 -> 文字 変換関数を使う
####################
procedure n2a1(n)
  return char(ord("A") +n -1)   # アルファベット A-Zはコード上で昇順に
end                             # 連続配置されている前提

##  2 ##############
# "AB..Z" の文字列の n番目指定を使う
####################
procedure n2a2(n)
  return &ucase[n]
       # ↑英大文字セット
end

##  3 ##############
# 文字置換関数を使う
####################
procedure n2a3(n)
  return case (n-1) / 10 of {
    0 : map(n -1,"0123456789","ABCDEFGHIJ")
    1 : map(n-11,"0123456789","KLMNOPQRST")
    2 : map(n-21,"012345"    ,"UVWXYZ")
  }
end

##  4 ##############
# tableを使う
####################
procedure n2a4(n)
  static Tn2a                   # 次回に呼ばれた時まで記憶
  initial {                     # 初回だけ実行
    Tn2a := table()             # table生成
    nn := 0                     # 文字の番号
    every s := !&ucase          # 'AB..Z'の文字セット から順に取り出す
      do Tn2a[nn +:= 1] := s    # tableへ登録 例: key:1 -> value:"A"
  }
  return Tn2a[n]                # table参照結果
end
-----$ N2A.ICN ( lines:58 words:184 ) ----------------------<cut here

  結果はこうなります。
-----^ N2A.1 ( date:03-10-23 time:23:55 ) ------------------<cut here
1-26を A-Zへ変換
n2a1: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
n2a2: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
n2a3: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
n2a4: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
-----$ N2A.1 ( lines:5 words:110 ) -------------------------<cut here

  Iconは、色んな方式のプログラムが楽しめますので、お試し頂けるとうれしいです。

風つかい(hshinoh@...)
IconのWWWは、  http://www.cs.arizona.edu/icon/
UniconのWWWは、http://unicon.sourceforge.net/index.html
BGM: Battery's not included / 森山威男 & 杉本喜代志