Loại bỏ mã chết


20

Mã chết ngồi đó không làm gì cả, nhìn chằm chằm vào chúng tôi biết rằng nó sẽ không bao giờ bị xử tử ... nhưng hôm nay chúng tôi có thể trả thù.

Đặc điểm kỹ thuật

Đầu vào sẽ là một chuỗi nhiều dòng.

Mỗi dòng có thể là một bài tập hoặc một biểu thức .

Bài tập

Một bài tập có dạng <name> = numbertrong đó tên là một chuỗi các chữ cái, dấu gạch dưới và số, nhưng không bắt đầu bằng một số.

Các biến có thể được chỉ định bất kỳ số lần.

Biểu hiện

Một biểu thức có dạng <var_name OR number> <operation> <var_name OR number> ...

Một biểu thức có thể là bất kỳ sự kết hợp nào của:

  • Các biến đã được xác định
  • Toán tử số học cơ bản +-*/
  • Số (số nguyên)

Sản lượng dự kiến

Bạn nên xuất chuỗi với các bài tập dự phòng , các bài tập không bao giờ được sử dụng bởi bất kỳ biểu thức nào sau nó, được loại bỏ. Xin lưu ý rằng các bài tập cũng có thể được thực hiện dự phòng nếu một phép gán bổ sung cho cùng một biến được thực hiện trước khi một biểu thức sử dụng biến được thực thi.

Các trường hợp thử nghiệm

trong

a = 10
a * 3

ngoài

a = 10
a * 3

trong

foo = 8
2 - 1
a = 18

ngoài

2 - 1

trong

a = 10
a = 8
b = 4
ab = 72  
b / 6
b + 1

ngoài

b = 4
b / 6
b + 1

trong

a = 1
a = 2
a + 1

ngoài

a = 2
a + 1

trong

FooBar1 = 0
Fuz__ = 8
Fuz__ / 1

ngoài

Fuz__ = 8
Fuz__ / 1

trong

a = 1
a + 1
a = 2
a + 1

ngoài

a = 1
a + 1
a = 2
a + 1

trong

a = 1
1 / 5 * 8 + 4

ngoài

1 / 5 * 8 + 4

trong

a = 1
a + 1
a = 1
a + 1

ngoài

a = 1
a + 1
a = 1
a + 1

trong

a = 7
5 / a

ngoài

a = 7
5 / a

1
Bạn có nên thêm trường hợp đặc biệt khó khăn này : a = 1; a + 1; a = 1; a + 1;? Trường hợp thứ hai chỉ a = 1có thể bị loại bỏ vì atrước đây được đặt thành cùng giá trị ( 1).
flodel

3
@flodel Không, không cần nhìn vào các giá trị
Caridorc

Hợp nhất @flodel testcase
Caridorc

Bạn nên thêm một trường hợp thử nghiệm trong đó một biến được sử dụng trong một biểu thức, nhưng không phải là phần tử đầu tiên của biểu thức. Đặc biệt quan trọng là thành viên cuối cùng của biểu thức.
isaacg

@isaacg không có mã chết, var có thể ở bất cứ đâu, đã thêm testcase
Caridorc

Câu trả lời:


9

PHP - 197 byte

Hàm này hoạt động bằng cách phân tích từng dòng, theo thứ tự ngược và lần lượt từng dòng và duy trì một mảng các biến được sử dụng.

  • Nếu có một ký tự bằng nhau =trong dòng, đó là một nhiệm vụ.
    • Đó là biến được sử dụng, phép gán rất hữu ích và dòng được in, nhưng biến không được xem là sử dụng nữa.
    • Nếu không, không làm gì cả.
  • Mặt khác, dòng là một biểu thức. Chúng tôi chia dòng sau mỗi khoảng trắng và thêm từng ký hiệu vào danh sách các biến được sử dụng. Các số ( 1,, 2) và toán tử ( +,, -) cũng sẽ được thêm vào, nhưng vì chúng không phải là tên biến hợp lệ, nên đó không phải là vấn đề. Các dòng sau đó tất nhiên được in.
function($c){$u=[];foreach(array_reverse(split('
',$c))as$l){if($p=strpos($l,'=')){if(!isset($u[$x=substr($l,0,$p-1)]))continue;
unset($u[$x]);}else$u+=array_flip(split(' ',$l));$f="
$l$f";}echo$f;}

Đây là phiên bản chưa được chỉnh sửa:

function removeDeadCode($code)
{
    $usedVariables = [];
    $finalCode = '';

    foreach (array_reverse(explode("\n", $code)) as $line)
    {
        if ($equalPosition = strpos($line, '='))
        {
            $variable = substr($line, 0, $equalPosition - 1);
            if (isset($usedVariables[$variable]))
            {
                $finalCode = "\n" . $line . $finalCode;
                unset($usedVariables[$variable]);
            }
        }
        else
        {
            $usedVariables += array_flip(explode(' ', $line));
            $finalCode = "\n" . $line . $finalCode;
        }
    }

    echo $finalCode;
}

7

Võng mạc , 45 byte

m`^(\w+) =.*\n(?=((?!\b\1\b)[^!])*(^\1 =|\Z))
<empty>

Đối với mục đích đếm, mỗi dòng đi trong một tệp riêng biệt (trong đó <empty>là một tệp trống) và \nnên được thay thế bằng nguồn cấp dữ liệu thực tế (0x0A).

Điều này giả định rằng chuỗi sẽ luôn kết thúc bằng một nguồn cấp dữ liệu.

Vì regex này không sử dụng bất kỳ tính năng dành riêng cho .NET nào, bạn có thể kiểm tra nó trên regex101 .

Ý tưởng khá đơn giản: loại bỏ tất cả các bài tập mà chúng ta có thể tìm thấy (tìm về phía trước) một bài tập khác cho cùng một biến hoặc kết thúc chuỗi mà không chuyển qua sử dụng biến khác.


6

Bình thường, 40 byte

eMf|!}K\=eT&Jf}+dhceTK++dYdPT!}KeJ_.__.z

Có vẻ hơi dài. Có lẽ tôi có thể lưu một hoặc hai byte vào ngày mai.

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Giải trình:

_.__.zđưa ra tất cả các hậu tố của các dòng đầu vào theo thứ tự đảo ngược. Ví dụ: đầu vào FooBar1 = 0; Fuz__ = 8; Fuz__ / 1đưa ra danh sách:

[['Fuz__ / 1', 'Fuz__ = 8', 'FooBar1 = 0'], 
 ['Fuz__ / 1', 'Fuz__ = 8']
 ['Fuz__ / 1']]

Sau đó, tôi lọc các phần tử danh sách T, trong đó =không có trong phần tử cuối cùng của T(biểu thức) hoặc (gán) phần tử cuối cùng trong Tđó chứa tên biến, là một biểu thức. Sau đó in phần tử cuối cùng của từng phần tử còn lại trên một dòng riêng biệt.

eMf|!}K\=eT&Jf}+dhceTK++dYdPT!}KeJ_.__.z
                                      .z  all input lines
                                     _    reverse order
                                   ._     all prefixes
                                  _       reverse order
  f                                       filter for elements T, which satisfy:
      K\=                                   K = '='
    !}K  eT                                 '=' is not in T[-1]
   |                                        or
             f             PT                 filter for elements Y in T[:-1],
                                              which satisfy:
                 hceTK                          extract variable name of T[-1]
                                                with an additional space at the end
               +d                               and at the beginning
              }       ++dYd                     ^ in space+Y+space
            J                                 assign these list to J
           &                                  J not empty and
                             !KeJ             '=' is not in J[-1]
eM                                        take the last element of each and print

8
.__.

Mã này không thành công trên pyth.herokuapp.com/
isaacg

@isaacg Đã sửa.
Jakube

4

CJam, 49 byte

LqN/W%{_'=#_){(<:V1$\e=_{\Va-\}&}{;S/+1}?},\;W%N*

Dùng thử trực tuyến

Cách tiếp cận ở đây là một danh sách các biến không được gán được duy trì trong khi xử lý các dòng đầu vào trở về trước:

  • Nếu dòng là một biểu thức, tất cả các biến trong biểu thức sẽ được thêm vào danh sách. Trên thực tế, trong quá trình triển khai, tất cả các mã thông báo được thêm vào danh sách, vì nó lưu mã và có số và toán tử trong danh sách không gây hại gì.

  • Nếu dòng là một phép gán, nó sẽ kiểm tra xem tên biến được gán có trong danh sách không. Nếu đúng, bài tập được chấp nhận và tên biến bị xóa khỏi danh sách. Nếu không, bài tập được bỏ qua.

Giải trình :

L     Start with empty list.
qN/   Get input and split at newlines.
W%    Reverse to process lines back to front.
{     Start of filter block.
  _     Copy line.
  '=#   Find equal sign.
  _     Copy position of equal sign, will use original later to extract
        variable name from assignment.
  )     Increment to produce truthy/falsy value (-1 from find means not found).
  {     Start if-block that processes assignments.
    (<    Slice off everything but variable name.
    :V    Save in variable V for later re-use.
    1$\   Place copy of unassigned variable list and new variable name at
          top of stack.
    e=    Count occurrences. This tells us if variable name was in list.
    _     Copy the condition value because it will also be used as the
          overall filter result.
    {     Start of block that removes variable name from list.
      \V    Bring list to top, and push variable name.
      a-    Remove the variable name from list.
      \     Swap to get variable list to bottom of stack for next iteration,
            and filter result to top.
    }&    End of conditional block to remove variable name.
  }     End of if-block for assignment.
  {     Start of else-block for expression.
    ;     Pop result of find operation.
    S/    Split expression at spaces.
    +     Concatenate the new variables with the existing ones in the list.
    1     Filter result, expressions are always accepted.
  }?    End of if for assignment vs. expression.
},    End of filter.
\;    Get rid of variable list at bottom of stack.
W%    Reverse order of filtered result, since we worked back to front.
N*    Join with newlines.

4

Python 2, 270 267 byte

import sys,re
d={}
s=list(enumerate(sys.stdin))
for n,l in s:
 try:v,_=l.split('=');v=v.strip();d[v]=d.get(v,[])+[[0,n]]
 except:
  for v in re.findall('[a-zA-Z_]\w*',l):d[v][-1][0]+=1
print''.join(l for n,l in s if n not in[n for x in d.values()for c,n in x if c==0])

Thụt lề là: 1. Không gian 2. Tab

Đã lưu 3 byte nhờ @Kamehameha!


Không gian sau khi in print ''.joininin in [ncó thể được gỡ bỏ.
Kamehameha

Ngoài ra, bạn có thể sử dụng thủ thuật này bằng cách sử dụng tabthay vì khoảng trắng kép sau exceptdòng và lưu một byte.
Kamehameha

2

R 144

Q=R=c()
for(L in rev(scan(,"",,,"\n"))){W=strsplit(L," ")[[1]]
if("="%in%W)if(W[1]%in%R)R=R[R!=W[1]]else next else R=c(R,W)
Q=c(L,Q)}write(Q,"")

Ở đâu

  • L là một dòng từ đầu vào (bắt đầu từ cái cuối cùng)
  • W là các ký hiệu (biến, toán tử, số) trong một dòng
  • Rlà một vectơ của các biểu tượng sẽ được in. Nó bao gồm các biến có sự phân công là cần thiết.
  • Q là vectơ của các dòng trong đầu ra

Bạn có thể thay thế scan(what="",sep="\n")bằng scan(,"",sep="\n"). Bạn cũng có thể thay thế sepđối số được đặt tên bằng đối số vị trí tương đương nhưng tôi không thể nhớ lại dấu phẩy sẽ đi đến đâu.
Alex A.

... tiết kiệm 6. Rất đẹp. Cảm ơn Alex!
flodel

2

JavaScript (ES6) 164 177

Sử dụng chuỗi mẫu, tất cả các dòng mới là quan trọng và được tính.

Kiểm tra chạy đoạn mã trong FireFox (cần thiết cho khả năng tương thích ES6 bao gồm các chức năng mũi tên)

f=s=>(k=>{s=s.split`
`,s.map((t,n)=>(r=t.match(/\w+/g)).map(v=>k[v]=f,~t.search`=`?k[s[k[v=r[0]]]=r[0]=0,v]=n:0))
for(v in k)s[k[v]]=0})([])||s.filter(r=>r).join`
`

ungolfed=s=>
{
  k={} // list line defining variables, by name, until used
  s=s.split`\n`
  s.forEach((t,n)=>
  {
    r=t.match(/\w+/g); // list variables in the line, operators are lost
    if (t.search`=` >= 0) // if it's an assignment
    {
      v=r[0] // new variable
      s[k[v]]=r[0]=0 // kill previous definition if not used
      k[v]=n
    }
    r.forEach(v=>k[v]='') // for each used variable, forget its definition line
  })
  for(v in k)s[k[v]]=0; // kill all remaining unused definitions
  return s.filter(r=>r).join`\n`
}

// TEST
out=x=>O.innerHTML+=x+'\n';


;[['a = 10\na * 3', 'a = 10\na * 3']
 ,['foo = 8\n2 - 1\na = 18','2 - 1'] 
 ,['a = 10\na = 8\nb = 4\nab = 72\nb / 6\nb + 1','b = 4\nb / 6\nb + 1'] 
 ,['a = 1\na = 2\na + 1','a = 2\na + 1'] 
 ,['FooBar1 = 0\nFuz__ = 8\nFuz__ / 1','Fuz__ = 8\nFuz__ / 1'] 
 ,['a = 1\na + 1\na = 2\na + 1','a = 1\na + 1\na = 2\na + 1']
 ,['a = 1\na + a\na = 2', 'a = 1\na + a']
 ,['a = 1\n1 / 5 * 8 + 4', '1 / 5 * 8 + 4']
 ,['a = 1\na + a\na = 2', 'a = 1\na + a']
 ,['a = 1\na + 1\na = 1\na + 1', 'a = 1\na + 1\na = 1\na + 1']
 ,['a = 7\n5 / a', 'a = 7\n5 / a']
]
.forEach(([i,k])=>(r=f(i),
  out('Test '+(r==k?'OK':'Fail')+'\nInput:  '+i.replace(/\n/g,',')
      +'\nResult: '+r.replace(/\n/g,',')
      +'\nCheck:  '+k.replace(/\n/g,',')+'\n')
));
Note: newlines trasformed to commas to save space in output
<pre id=O></pre>


Này, đó không phải là 164 byte!
Cyphase

@Cyphase dòng 1:20 + 1 dòng mới, dòng 2; 92 + 1 dòng mới, dòng 3:48 + 1 dòng mới, dòng 4: 1. 21 + 93 + 49 + 1 => 164. Phần ungolfednày chỉ dành cho giải thích. Phần TESTlà ... uhm chỉ cần đoán ...
edc65

Tôi biết. Tôi chỉ đùa thôi. Lấy làm tiếc :).
Cyphase

1

JavaScript ES6, 79 75 118 byte

s=>s.split`
`.filter((l,i,a)=>(q=l.split`=`)[1]?!~(a.slice(i+1)+0).search(q[0]+'=')&&~s.search(q[0]+'[^=]'):1).join`
`

Hãy cho tôi biết nếu điều này không làm việc cho một trường hợp. Bất kỳ ý tưởng cho việc chơi golf đều được chào đón.


Giải trình

s=>          // Function with argument "s"
  s.split`   // Splits each line
  `
  .filter(   // Filters through each line,
    (item,index,array)=>
      (q=l.split`=`)[1]? // If there is something after the equal sign
        !~ // XOR (~) will  essentially make -1, 0. NOT (!) will make 0, 1, vice-versa
         (a.slice(i+1)+0) // Gets following lines
         .search`^${z=q[0]}=` // Checks if following lines have the same variable name and then =
        && // AND...
         ~s.search(z+'[^=]') // Check if there is an expression with the variable
        :1) // If there is no equal sign, return 1 (true)
  .join` // Join everything back, seperated by newlines
  `

Đã thử nghiệm trên Safari hàng đêm. Phiên bản thân thiện với Firefox:

s=>s.split`
`.filter((l,i,a)=>(q=l.split`=`)[1]?!~(a.slice(i+1)+0).search(`^${z=q[0]}=`)&&~s.search(z+'[^=]'):1).join`
`

Bạn có thể tham gia babeljs để có phiên bản ES5.


@Blackhole Tôi đã sửa nó.
Hạ cấp

@ edc65 theo các ví dụ, dấu phân cách là một dòng mới. Đầu vào cũng ở một định dạng nghiêm ngặt với các khoảng trắng, v.v.
Hạ cấp

@ edc65 Bạn có chắc không? Hãy thử gói hàm trong ngoặc đơn và chạy nó như thế. Nó hoạt động với tôi (Safari Nightly).
Hạ cấp

Có thể tôi quá cố chấp nhưng tôi vẫn cảm thấy quá đơn giản để làm việc tốt trong mọi trường hợp. Tôi đã làm cho nó chạy mà không có lỗi trong Firefox thêm dấu ngoặc trong cuộc gọi tìm kiếm (vẫn ngắn hơn so với của tôi). Và đã thử "a = 1 \ na + a \ na = 2". Và nó thất bại ...
edc65

Thx đã thêm đề nghị của tôi vào câu trả lời của bạn. -1 vì nó vẫn bị lỗi
edc65

1

Haskell, 187 byte

Sử dụng d.

import Data.List
f=filter
(!)=map
b((v,e,w):t)=e||or((\(_,p,_)->p)!take 1(f(\(x,_,y)->v==x||v`elem`y)t))
d=unlines.(\l->snd!f fst(zip(b!tails(((\(v:o:w)->(v,o/="=",w)).words)!l))l)).lines
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.