SASマクロ変数を解決する


13

SASプログラミング言語は、まだ使用中今日の1966年に不格好、古風な言語デートバックです。元のコンパイラはPL / Iで記述されており、実際、構文の多くはPL / Iから派生しています。SASには、PL / Iの言語から派生したプリプロセッサマクロ言語もあります。この課題では、SASマクロ言語のいくつかの単純な要素を解釈します。

SASマクロ言語では、%letキーワードを使用してマクロ変数が定義され、ログへの出力はで行われ%putます。ステートメントはセミコロンで終わります。ここではいくつかの例を示します。

%let x = 5;
%let cool_beans =Cool beans;
%let what123=46.lel"{)-++;

マクロ変数名は大文字と小文字を区別せず、常に正規表現と一致します/[a-z_][a-z0-9_]*/i。この課題のために、次のように言います。

  • マクロ変数は、印字可能なASCII文字のみで完全に成るの値を保持することができます以外に ;&%
  • 値に先頭または末尾のスペースはありません
  • 値は255文字を超えることはありません
  • 値は空かもしれません
  • 値の中の括弧と引用符は一致しない場合があります
  • そこの前後にスペースの任意の量であることができる=%let声明と、このスペースは無視されるべきです
  • ステートメント;内の端末の前に任意の量のスペースがあり%let、このスペースも同様に無視する必要があります

マクロ変数が呼び出されるとき、その値に「解決」すると言います。マクロ変数は、先頭に付加することで解決され&ます。識別子の終わりを示すオプションの末尾があり.ます。例えば、

%put The value of x is &X..;

The value of x is 5.ログに書き込みます。1つの期間がに消費され&X.、解決されるため、2つの期間が必要であることに注意してください5。またx、小文字で定義したにもかかわらず、マクロ変数名では大文字と小文字が区別されないため&X、同じ&xです。

ここで注意が必要です。複数&のを一緒に連結して変数を解決&し、同じレベルのネストを同時に解決できます。例えば、

%let i = 1;
%let coolbeans1 = broseph;
%let broseph = 5;

%put &&coolbeans&i;  /* Prints broseph */
%put &&&coolbeans&i; /* Prints 5 */

最も内側&のが最初に解決され、解像度は外側に向かって続きます。変数名のマッチングは貪欲に行われます。2番目の%putステートメントでは、プロセッサは次の手順を実行します。

  1. &iに解決し1、最も内側のリード&が消費されて、&&coolbeans1
  2. &coolbeans1に解決しbroseph、私たちに与えます&broseph
  3. &brosephに解決され5ます。

末尾に.s がある場合.、解像度が複数ある場合でも、1つだけが解像度で消費されます&のです。

仕事

%let改行と単一の%putステートメントで区切られた1〜10個のステートメントを指定すると、%putます。入力は任意の標準的な方法で受け入れることができます。

入力は常に有効であり、%letステートメントはステートメントの前にあると想定でき%putます。定義された変数は、後の%letステートメントで再定義されません。

実際にSASで実行する場合、存在しない変数に解決する変数に問題はなく、上記のようにすべてが構文的に正しいでしょう。

  1. 入力:

    %let dude=stuff;
    %let stuff=bEaNs;
    %put &&dude..;
    

    出力:

    bEaNs.
    
  2. 入力:

    %let __6 = 6__;
    %put __6&__6;
    

    出力:

    __66__
    
  3. 入力:

    %let i=1;
    %let hOt1Dog = BUNS;
    %put &&HoT&i.Dog are FUNS&i!");
    

    出力:

    BUNS are FUNS1!")
    
  4. 入力:

    %let x = {*':TT7d;
    %put SAS is weird.;
    

    出力:

    SAS is weird.
    
  5. 入力:

    %let var1   =  Hm?;
    %let var11 = var1;
    %let UNUSED = ;
    %put &&var11.....;
    

    出力:

    Hm?....
    

    &&var11一致するvar11名前の一致は貪欲であることから。があった場合.、つまり&&var1.1var1一致し、余分な1は名前の一部にはなりません。

これはコードゴルフであるため、バイト単位の最短ソリューションが勝ちです!


テストケース1からの出力には、どのような期間がありますか?&stuff.期間を削除すべきではありませんか?
GamrCorps

@GamrCorpsを指定する必要があります:単一の後続期間のみが解像度で消費されます。
アレックスA.

@GamrCorps編集してテストケースとして指定および追加しました。
アレックスA.

そう&&&&&&&&&a......................、まだ一つだけの期間を削除しますか?
GamrCorps

@GamrCorpsはい。
アレックスA.

回答:


1

Pythonの3354の 341 336バイト

import re
S=re.sub
def f(x):
	r=x.splitlines();C=r[-1].strip('%put ');D=0
	while D!=C:
		D=C
		for a in sorted([l.strip('%let ').replace(" ","").split(';')[0].split('=')for l in r[:-1]],key=lambda y:-len(y[0])):
			s=1
			while s:C,s=re.subn('&'+a[0]+'(\.?)',a[1]+'😍\\1',S('😍+\.([^\.])','\\1',C),0,re.I)
	return S('😍+\.?','',C)

オンラインでお試しください!

編集:いくつかの簡単な短縮

編集:[::-1](5バイト)の代わりに-len(...)による逆ソート、ジョナサンフレッチのおかげ!

非ゴルフ

import re
S=re.sub # new name for the function re.sub()
def f(x):
    r=x.splitlines() # input string to list of rows
    C=r[-1].strip('%put ') # get the string to put (from the last row)
    D=0
    while(D!=C): # iterate until the result does not change
        D=C
        for a in                                                                                                                    : # iterate over the list of variables
                 sorted(                                                                          ,key=lambda y:len(y[0]),reverse=1) # sort list for greediness by decreasing var.name lengths
                        [l.strip('%let ') # cut the 'let' keyword
                                         .replace(" ","") # erase spaces
                                                         .split(';')[0] # cut parts after ';'
                                                                       .split('=') # create [variable_name,value] list
                                                                                  for l in r[:-1]] # for each row but last
            s=1
            while(s): # iterate until the result does not change
                C,s=re.subn( # substitute
                            '&'+a[0]+'(\.?)', # &varname. or &varname
                                                 a[1]+'😍\\1', # to value😍. or value😍
                                                              S('😍+\.([^\.])','\\1',C), # in the string we can get from C erasing (😍's)(.) sequences if the next char is not .
                                                                                        0,re.I) # substituting is case insensitive
    return S('😍+\.?','',C) # erase smileys and one .

Pythonのヒントページをよくお読みになることをお勧めします。非複合ステートメントの連結(;)、括弧の削減(if(...)-> if ...)、リスト操作(,reverse=1-> [::-1])などの簡単な最適化により、いくつかのバイトを簡単に節約できます。
ジョナサンフレッチ

ありがとう!私は以前にそれを読んだことがありますが、それはかなり前のことであり、私はいくつかのトリックを忘れていました。
mmuntag

どういたしまして。len(y[0]))[::-1]することができます-len(y[0]))
ジョナサンフレッチ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.