แก้ไขตัวแปรแมโคร SAS


13

ภาษาการเขียนโปรแกรม SASเป็น clunky โบราณภาษาย้อนหลังไปถึง 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.ลงในบันทึก โปรดทราบว่าสองช่วงจะต้องเพราะเป็นระยะเวลาเดียวจะนำมาบริโภคโดยและมีมติให้&X. 5โปรดทราบว่าแม้ว่าเราจะกำหนดเป็นxตัวพิมพ์เล็ก แต่&Xก็เป็น&xเพราะชื่อตัวแปรมาโครนั้นไม่ตรงตามตัวพิมพ์เล็กและใหญ่

นี่คือสิ่งที่มันยุ่งยาก หลาย&s สามารถรวมเข้าด้วยกันเพื่อแก้ไขตัวแปรและ&s ที่ระดับเดียวกันของการซ้อนการแก้ไขในเวลาเดียวกัน ตัวอย่างเช่น,

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

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

วิธี&แก้ปัญหาที่อยู่ด้านในสุดก่อน การจับคู่ชื่อตัวแปรทำอย่างตะกละตะกลาม ใน%putคำสั่งที่สองตัวประมวลผลทำขั้นตอนต่อไปนี้:

  1. &iแก้ไขให้1และผู้นำด้านในสุด&ถูกบริโภคให้เรา&&coolbeans1
  2. &coolbeans1แก้ไขเพื่อbrosephให้เรา&broseph
  3. &broseph5มีมติให้

หากมีการต่อท้าย.s จะมีการ.ใช้ความละเอียดเพียงอันเดียวแม้ว่าจะมีหลาย&s ก็ตาม

งาน

รับระหว่าง 1 ถึง 10 %letคำสั่งคั่นด้วยการขึ้นบรรทัดใหม่และ%putคำสั่งเดียวพิมพ์หรือส่งคืนผลลัพธ์ของ%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.1นั้นvar1จะได้รับการจับคู่และพิเศษ 1 จะไม่เป็นส่วนหนึ่งของชื่อใด ๆ

นี่คือรหัสกอล์ฟดังนั้นทางออกที่สั้นที่สุดในหน่วยไบต์ชนะ!


เอาต์พุตจากกรณีทดสอบ 1 มีระยะเวลาอย่างไร ไม่ควร&stuff.ลบช่วงเวลานี้ใช่ไหม
GamrCorps

@GamrCorps ฉันควรระบุ: ใช้ระยะเวลาการสืบค้นกลับเพียงครั้งเดียวในการแก้ปัญหา
Alex A.

@GamrCorps แก้ไขเพื่อระบุและเพิ่มเป็นกรณีทดสอบ
Alex A.

ดังนั้น&&&&&&&&&a......................จะยังคงลบหนึ่งช่วงเวลาเท่านั้น?
GamrCorps

@GamrCorps ใช่
Alex A.

คำตอบ:


1

Python 3 , 354 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)

ลองออนไลน์!

แก้ไข: ตัดทอนบางอย่างง่าย

แก้ไข: จัดเรียงย้อนกลับโดย -len (... ) แทน [:: - 1] (5 ไบต์) ขอบคุณ Jonathan Frech!

Ungolfed

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 .

ผมจะแนะนำการเป็นจำนวนมากที่งูหลามเคล็ดลับหน้า การปรับให้เหมาะสมเล็กน้อยเช่นการตัดแบ่งคำสั่งไม่ผสม ( ;) การลดวงเล็บ ( if(...)-> if ...) และการดำเนินการรายการ ( ,reverse=1-> [::-1]) สามารถบันทึกได้อย่างง่ายดายบางไบต์
Jonathan Frech

ขอบคุณ! ฉันเคยอ่านมาก่อน แต่มันนานมาแล้วและฉันลืมเทคนิคบางอย่าง
mmuntag

ยินดี. สามารถlen(y[0]))[::-1] -len(y[0]))
Jonathan Frech
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.