폴리 글 로트 생성을위한 팁


48

2 개 이상의 서로 다른 프로그래밍 언어에서 실행할 수있는 프로그램입니다.

폴리 글 로트를 만들거나 특정 작업에 대해 폴리 글 로트를 작성하기 쉬운 언어를 선택하기위한 일반적인 팁은 무엇입니까?

대부분의 상황에서 적용될 수있는 팁을 게시하십시오. 즉, 그들은 두 가지 특정 언어의 폴리 글 로트에서만 작동해서는 안됩니다. (너무 구체적인 팁이 있으면 간단히 폴리 글롯 질문에 대한 답변을 게시 할 수 있습니다.) 그러나 많은 언어로 쉽게 작업하거나 기존 폴리 글 로트에 쉽게 추가 할 수있는 언어 기능을 도입 할 수 있습니다.

답변 당 하나의 팁을 게시하십시오. 언어 별 팁이 다른 언어에도 적용되는 경우 편집을 제안하십시오.

답변:


25

주석 기호 악용

2 개 언어 폴리 글롯을 만드는 간단한 방법은 다음과 같이 코드를 두 부분으로 나누는 것입니다.

  1. 첫 번째 부분은 언어 A에서 실제 작업을 수행하고, 언어 B에서 오류가 없으며 (오류 없음), 두 번째 부분을 언어 A로 숨기는 언어 A 주석 기호로 끝납니다.
  2. 두 번째 부분은 언어 B의 실제 작업을 수행합니다.

그러므로

  • 언어 A는 첫 번째 부분을보고 작업을 수행 한 다음 주석을 표시합니다.
  • 언어 B는 쓸모없는 첫 번째 부분을 보았고 두 번째 부분을 보았습니다.

여기서 유일한 어려운 부분은 언어 B에서 오류를 발생시키지 않으면 서 언어 A에서 작업을 수행하는 일련의 명령문 (첫 번째 부분)을 찾는 것입니다.

  • 대부분의 스택 기반 언어는 프로그램 끝에서 스택의 맨 위만 표시 할 수 있습니다 (때로는 05AB1E에서와 같이 기본값 임).
  • 일부 언어는 정의되지 않은 명령문 (예 : Golfscript)을 무시합니다.

이러한 지침을 사용하는 간단한 예는 여기 에서 찾을 수 있습니다 . 언어 A와 B는 각각 MATL05AB1E 입니다.


24

2 차원 언어 사용

일반적으로 전체 소스 코드를 구문 분석하고 이해하지 못하는 것에 구문 오류 또는 원치 않는 런타임 효과를 생성하는 1 차원 언어와 달리 (따라서 다른 언어의 코드를 숨기도록 강요) 2 차원 언어는 실행 경로에서 코드를 구문 분석하십시오. 이는 프로그램의 나머지 전체가 무시됨을 의미합니다. 또한 실행 경로를 2 차원으로 분리 할 공간이 훨씬 더 많습니다. 명령 포인터를 아래쪽이나 왼쪽 (프로그램의 오른쪽으로 감싸는 등)과 같은 비정상적인 방향으로 돌리면 매우 빠르게 벗어날 수 있습니다. 1 차원 언어에 유용한 기술은 2 차원 언어로 일반화됩니다 (예 :;; Befunge-98에서 IP를 이상한 방향으로 보내는 것 외에도 1 차원 솔루션에 비해 엄격한 이득을 얻습니다.

보너스로, 몇몇 2 차원 언어는 프로그램의 왼쪽 상단 이외의 진입 점을 가지므로 다른 언어와 분리하기 위해 노력할 필요가 없습니다. 그들은 그룹에서 자연스럽게 분리 될 것입니다.


20

당신의 진실과 거짓을 아십시오

각 언어는 "참"과 "거짓"이 약간 다르게 보입니다. 구문이 비슷한 경우 언어가 다르게 처리 될 것이라는 결정을 추가하여이를 활용할 수 있습니다.

Trick 또는 Treat 스레드의 한 예'' 는 빈 문자열 인을 사용 합니다. 루아에서 이것은 진실로 평가되지만 파이썬에서는 거짓입니다.

print(''and'trick'or'treat')

.. 언어마다 다른 문자열을 인쇄합니다.

필요한 것은 이와 같은 가치를 찾는 것입니다. 예를 들어, PHP 에서는 파이썬으로 '0'평가되는 false을 사용할 수 있습니다 true.


17

적어도 하나의 언어로 인용구

다음은 Python과 C ++에서 모두 작동하는 예제입니다.

#include <iostream> /*
""" */
int main() {
    std::cout << "Hello World!\n";
}

/* """
print("Hello World!")
# */

Luis Mendo 는 의견을 사용하는 것이 가장 쉬운 해결책이라고 생각했습니다.

첫 번째의 일반 구문이 두 번째의 구문에 주석을 달고있는 블록 주석이있는 언어와 다른 언어를 찾습니다.

서로 다른 블록 주석 스타일을 가진 두 언어가 더 쉬워서 구문이 바뀔 수 있지만 확인하기가 귀찮았습니다.

Python 3.5C ++ 에서 확인하십시오.


2
첫 번째 줄에는 세미콜론이 없어야합니다.

참된. 좋은 지적
dexgecko

15

나누고 정복

많은 언어로 폴리 글롯을 작성할 때 모든 언어 제어 흐름을 서로 즉시 분리 할 수있는 것은 아닙니다. 따라서 일부 언어를 일정 기간 동안 "참 폴리 글 로트"하여 각 언어에서 동일한 코드를 실행할 수 있어야합니다. 이 작업을 수행하는 동안 명심해야 할 두 가지 기본 규칙이 있습니다.

  • 두 언어의 제어 흐름은 매우 유사하거나 매우 달라야 합니다. 많은 수의 인터리브 된 제어 흐름을 처리하려고하면 혼란스러워지고 프로그램을 수정하기가 어렵습니다. 대신, 같은 장소에있는 모든 프로그램이 같은 이유로 존재하고 필요할 때 행복하게 병렬로 실행될 수 있도록해야 할 일의 양을 제한해야합니다. 한편, 언어가 다른 언어와 매우 다른 경우, 실행을 가능한 빨리 다른 위치로 옮기기를 원하므로 한 번에 두 개의 다른 구문 모델을 준수하도록 코드를 만들 필요가 없습니다.

  • 한 언어 또는 유사한 언어 그룹을 서로 분리 할 수있는 기회를 찾으십시오. 더 큰 그룹에서 더 작은 그룹으로 작업하십시오. 프로그램의 특정 지점에 유사한 언어 그룹이 모두 있으면 특정 지점에서 언어를 분리해야합니다. 프로그램을 시작할 #때 주석 표시로 사용되는 언어를 다른 주석 표시 를 사용하는 언어에서 분리하려고 할 수 있습니다 . 나중에 모든 언어 f(x)가 함수 호출에 구문을 사용 하고 세미콜론으로 명령을 구분하며 구문 상 유사성이 비슷한 점이있을 수 있습니다. 이 시점에서 루비와 펄이 ''문자열 에서 이스케이프 시퀀스를 처리하지 않지만 파이썬과 자바 스크립트가 처리한다는 사실과 같이 언어별로 더 많은 것을 사용하여 분할 할 수 있습니다.

일반적으로 프로그램의 논리적 흐름은 트리로 끝나고 서로 비슷한 언어 그룹으로 반복해서 분할됩니다. 이로 인해 첫 분할 이전에 폴리 글롯을 작성하는 데 어려움이 대부분 발생합니다. 제어 흐름이 점점 더 많이 분출되고 특정 지점에서 실행되는 언어가 점점 더 유사 해짐에 따라 구문 오류와 관련된 언어를 유발하지 않고도 고급 구문을 사용할 수 있으므로 작업이 쉬워집니다.

좋은 예는 {JavaScript, Ruby, Perl, Python 3}; 이러한 모든 언어는 괄호로 함수 호출을 허용하며 세미콜론으로 명령문을 분리 할 수 ​​있습니다. 또한 모두 eval효율적으로 흐름 제어를 수행 할 수 있는 명령문을 지원합니다 . (Perl은 다른 언어와는 다른 변수 구문을 가지고 있기 때문에 그룹에서 일찍 분리하는 데 가장 적합한 언어입니다.)


13

문자열 리터럴 내에서 코드 숨기기

대부분의 언어에서 문자열 리터럴 자체는 아무 작업도 수행하지 않거나 쉽게 뒤집을 수있는 작업 (예 : 문자열을 스택으로 푸시)을 수행합니다. 문자열 리터럴 구문은 비교적 표준화되지 않았으며, 특히 많은 언어에서 개행 문자가 포함 된 문자열을 처리하는 데 사용하는 대체 구문의 경우에는 상대적으로 표준화되지 않았습니다. 예를 들어 Python은 """ ... """, Perl은 q( ... ), Lua는을가집니다 [[ ... ]].

이 두 가지 주요 용도가 있습니다. 하나는 한 언어의 첫 번째 섹션 끝에서 문자열을 시작하고 두 번째 시작 부분에서 다시 시작하여 다른 언어로 된 섹션을 인터리브하는 것입니다. 다양한 언어로 인해 실수로 문자열을 닫는 것을 피하는 것이 매우 쉽습니다. 여러 언어 중에서 문자열 구분 기호 다른 하나는 많은 문자열 구분 기호가 다른 언어 (주로 주석 표시 자보다 더 많은 명령)의 명령으로 의미가 있기 때문에 x = [[4] ]JSON 표기법을 목록에 사용하지만 언어로 시작하는 언어에서는 무해한 할당입니다. Lua의 문자열 (따라서 Lua 코드를 나머지에서 효과적으로 "점프"하는 경우 Lua 코드를 분할 할 수 있습니다 ]]).


13

프로그램 종료

다른 언어의 코드를 무시하도록 한 언어로 프로그램을 갑자기 종료 할 수 있습니다.

기본적으로이 형식을 사용할 수 있습니다

code_in_language1 end_program_in_language1 code_for_language2 end_program_in_language2 ...

end_program_in_languageN프로그램을 끝내기위한 명령은 어디에 있습니까 ?

예를 들어, 추수 감사절 에는 무엇을 가져 오겠습니까? Dip에서 프로그램을 종료 한 다음 Dip 인터프리터가 무시할 수 있도록 다른 언어 V를위한 코드를 작성했습니다.

"turkey"e#"corn"??"gravy"p&Ssalad
"turkey"e#"corn"??"gravy"                 
                         p&            # print stack and exit program (Dip) 
                           Ssalad      # Now that the program ended in Dip,
                                       # I can write V code that would otherwise
                                       # have caused errors in Dip

그러나 모든 언어에 프로그램을 종료 할 수있는 명령이있는 것은 아닙니다. 그러나 그러한 언어에 특징이있는 경우 현명하게 사용해야합니다.

@LuisMendo가 제안한 것처럼, 언어에 이미 "종료 프로그램"이 내장되어 있지 않으면 프로그램을 종료하는 오류 (허용되는 경우)를 작성할 수 있습니다.


2
언어에 프로그램을 종료하는 기능이나 문장이 없더라도 오류가 발생합니다.
Luis Mendo

1
@LuisMendo : 동의하지만 많은 폴리 ​​글로 팅 문제는 종료를 통한 충돌을 금지합니다. 하지만 그렇지 않을 때는 악용하는 것이 좋습니다.

1
두 번째 부분의 코드는 여전히 제 1 언어에서 구문 상 정확해야하며 그렇지 않으면 대부분의 실제 언어에서 오류가 발생합니다.
MilkyWay90

13

문자열 리터럴 내의 변수 또는 코드

큰 따옴표로 묶인 문자열 리터럴은 대부분 여러 언어에서 무해합니다. 그러나 일부 언어에서는 코드를 포함 할 수도 있습니다.

Bash에서는 다음을 사용할 수 있습니다 `...`(프로그램을 종료하지 않음).

"`echo Hello world! >/proc/$$/fd/1`"

Tcl에서는 다음을 사용할 수 있습니다 [...].

"[puts {hello world!};exit]"

PHP에서는 다음을 사용할 수 있습니다 ${...}(Bash에서 오류가 발생하여 Bash 코드 뒤에 표시되어야 함).

"${die(print(Hello.chr(32).world.chr(33)))}";

루비에서는 다음을 사용할 수 있습니다 #{...}.

"#{puts 'Hello world!';exit}"

다른 사람도있을 수 있습니다.

이 문법은 호환되지 않습니다. 즉, 이러한 언어의 모든 코드를 하나의 문자열로 무해한 위치에 둘 수 있습니다. 그리고 다른 언어에서는 인식 할 수없는 코드를 무시하고 문자열 내용으로 해석합니다.

대부분의 경우 큰 따옴표 문자를 쉽게 주석 처리하고보다 전통적인 폴리 글롯을 만들 수 있습니다.


12

변수 앨리어싱

이것은 아마도 가장 많은 언어에 도달 할 수 있기 때문에 가장 단순하지만 (IMO) 가장 중요한 트릭 중 하나 일 것입니다.

예:

print=alert;print("Hello World!")

이것은 자바 스크립트뿐만 아니라 Python, Ruby 등에서도 작동합니다. 나중에 다른 사람들을 생각할 때 더 많은 예제가 있습니다. 물론, 의견 제안 / 사후 편집을 환영합니다.


5
예를 들어 JS / Python을 수행 할 때 JS의 주석 구문 은 Python 프로그램에서 쉽게 작업 할 수 있지만 Python 은 JS로 작업 할 수 없기 때문에 일반적으로 Python에서 앨리어싱 alert하기 print가 짧습니다 (3 만) . //#
ETHproductions

11

#기반 댓글

이 팁은 하나 이상의 언어로 된 악용 주석 기호인용 부호 의 하위 집합입니다.

많은 언어, 특히 esolang과 달리 생산 준비 언어로 폴리 글 로트를 작성할 때 #블록 또는 한 줄 주석에 사용되는 언어를 보는 것이 유용 할 수 있습니다 .

  • 로 시작하는 블록 주석 구문을 가진 많은 언어가 있으며 #, 다음에 오는 문자에는 다양한 종류가 #있습니다.
  • 이러한 언어의 대부분은 단일 #주석으로 한 줄 주석을 허용합니다. 즉, 한 언어에서 블록 주석을 시작할 수있는 것은 다른 언어에서는 일반적인 주석 일 뿐이므로 쉽게 맞출 수 있습니다.

다음 #은 블록 주석에 사용 되는 언어에 대한 간단한 요약 목록입니다 (완전하지는 않음).

Language            Start       End      Single-line #?     Notes
------------------------------------------------------------------------------------------
Agena               #/          /#             ✓
AutoIt              #cs         #ce
Brat                #*          *#             ✓
C                   #if 0       #endif                      Not actually a comment
CoffeeScript        ###         ###            ✓            Needs to be on separate line
Common Lisp         #|          |#
Julia               #=          =#             ✓
Lily                #[          ]#             ✓
Objeck              #~          ~#             ✓
Perl 6              #`{         }#             ✓            Any bracketing chars will do
Picolisp            #{          }#             ✓
Scheme              #|          |#

자세한 예는 Rosetta Code를 참조하십시오 .

다음은 데모로 빠르고 쉬운 예입니다.

#|
###
#`[

print("Julia")
#=

|#
(format t "Common Lisp")
#|

###
alert("CoffeeScript")
###

]#
say "Perl 6"
#`[

...

# ]# # ### # |# ; =#

제퍼#- ... -#있습니다.
DLosc

11

산술 연산자 불일치

비슷한 언어 나 간단한 폴리 글 로트의 경우 언어가 산술을 수행하는 방법의 차이점을 찾는 것이 유용한 경우가 있습니다. 비 (비 비전) 언어에는 대부분 산술 연산자가 있으며 산술은 차이를 빠르고 쉽게 도입 할 수 있기 때문입니다.

예를 들면 다음과 같습니다.

  • ^ 일부 언어에서는 비트 XOR이고 다른 언어에서는 지수입니다
  • / 일부 언어에서는 정수 나누기, 다른 언어에서는 부동 소수점 나누기
    • 정수 분할 언어의 경우 -1/2입니다 -1일부 언어 (내림)과 0다른 사람 (제로 원)
  • -1%2입니다 -1일부 언어와 1다른 사람
  • --x 일부 언어 (이중 부정)에서는 사용하지 않으며 다른 언어에서는 사전 감소
  • 1/0 일부 언어에서는 무한대를 제공하고 다른 언어에서는 오류를 제공합니다
  • 1<<64일부 언어 (오버플로) 및 36893488147419103232기타 언어로 0 제공

3
간단한 예는이 x=1;["JS","Python"][--x]언어가 실행되는 언어의 이름 (JS와 Python 사이)을 반환합니다.
ETHproductions

10

Brainfuck 사용

거의 모든 BF 구현은 그렇지 않은 문자를 캐스트 +-<>[].,하므로 우리에게 유리하게 작동합니다!

BF 파트를 먼저 작성하는 한 BF 는이 기능으로 인해 폴리 글 로트 작업에 가장 쉬운 언어 중 하나 일 것입니다 . 당신이 당신의 BF 코드를 기입하면, 그것은 당신이 다른 어떤 코드 모델링 단지 문제 의 주위에 BF 구조.

다음은 정말 간단한 예입니다.

.+[.+]

이것은 런타임 설정에 따라 "영원히"증가하고 문자 출력합니다. JS에서 임의의 코드 조각을 작성하려면 다음과 같이하십시오.

x=>"asdf".repeat(+x)[x*Math.random()*2+1|0]

JS가 BF를 중심으로 어떻게 만들어 졌는지 주목하십시오.

실제로 BF로 시작하는 경우 이것이 가장 효과적이라는 것을 알아야합니다. 다른 언어로 시작하고 BF를 통합하는 것은 상당히 어렵습니다.


6
BF 통합으로 인한 몇 바이트의 절약이 큰 도움이되지 않는 더 큰 폴리 글 로트의 경우 BF를 마지막으로 작성 하고 다른 코드 []를 필요한 만큼 랩핑합니다 .
Sp3000

6
이것은 brainfuck뿐만 아니라 수많은 brainfuck-similar 언어와 다른 많은 Turing tarpit에도 적용됩니다.
0

2
첫 번째 x=>는 셀을 변경하는데,이 경우에는 중요하지 않지만 그냥 말하고 싶었다
Roman Gräf

7

대부분의 문자가 중요하지 않은 언어를 사용하십시오.

이것은 BF에 관한 Mama Fun Roll의 요점을 일반화 한 것입니다 . 대부분의 문자를 무시하는 esolang은 폴리 글 로트에 매우 유용합니다. 큰 문자 집합을 서로 바꿀 수있는 esolang도 유용합니다. 몇 가지 예 :

  • 공백공백 , 탭 또는 줄 바꿈이 아닌 모든 것을 무시합니다.
  • Brain-Flak은 기본적으로 이외의 모든 것을 무시합니다 ()[]{}<>. ( @때로는 인터프리터가 디버그 플래그의 시작으로 해석하려고 할 때 오류가 발생합니다.)
  • oOo CODE 는 문자를 제외한 모든 것을 무시합니다. 또한 모든 대문자와 마찬가지로 모든 소문자를 서로 바꿀 수 있습니다.
  • Wierd 는 공백 문자와 공백이 아닌 문자 만 구분합니다.
  • 에서 워디 , 일부 문장 부호는 무시되고, 모든 문자는 교환 할 수있다.
  • 괄호괄호 모두 괄호를 제외한 모든 것을 무시합니다.

@오류를 수정했습니다 .
밀 마법사

Whitespace와 Python을 결합 해보십시오
enedil

@enedil 파이썬으로 탭을 가질 필요는 없습니다. 다음을 사용할 수 있습니다exec('''...\t\n\40''')
MilkyWay90

5

중첩 된 블록 주석에주의하십시오

때때로 여러 언어가 블록 주석에 동일한 구문을 사용하는데, 이는 종종 두 언어로 폴리 글 로트를 생성하기위한 거래 차단기가 아닙니다. 그러나 매우 가끔 언어 중 하나에서 중첩 된 블록 주석이 허용되므로 악용되어 별도의 코드 경로를 만들 수 있습니다.

예를 들어,이 폴리 글롯을 고려하십시오.

#[#[]#print("Lily")#]#echo"Nim"

Nim과 Lily는 블록 주석을 사용 #[하여 ]#블록 주석을 시작 및 종료하지만 Nim 만 중첩 된 블록 주석을 허용합니다.

Lily는 두 번째 #[를 단일 블록 주석의 일부로 간주하고 첫 번째 ]#를 블록 주석 종료로 간주합니다. ( #다음 Lily의 인쇄 문은 Nim의 코드를 숨기는 라인 주석입니다.)

다른 방법으로,을 #[]#중첩 된 (비어 있지만) 블록 주석 및 print("Lily")#외부 블록 주석으로 간주합니다.


4

이것이 중요한지 확실하지 않지만 ...

shebang 라인을 사용하여 모든 것을 유효한 perl프로그램 으로 바꾸십시오.

이 답변 과 Perl 설명서 에 따르면 shebang 줄로 시작하는 파일을에 전달 perl하면 해당 프로그램이 실행됩니다. 예를 들어

#!/usr/bin/python

for i in range(6):
    print i**2

를 호출하면 Python 인터프리터에 의해 실행됩니다 perl filename.py.


3
프로그램을로 호출 할 수 있지만 perlPerl 프로그램은되지 않습니다.
Paŭlo Ebermann 10

2
@ PaŭloEbermann 나는 그것이 경계선이라는 것을 깨달았습니다. 그래서 나는 그것이 "가치인지 확실하지 않은"것으로 대답을 시작했습니다. :) 그러나 "문서에 쓰여지고 참조 구현에 의해 반환되는"것이 아닌 경우 진정한 Perl을 정의하는 것은 무엇 perl입니까? 좋은
철학자


4

존재하지 않는 함수를 호출 한 다음 인수를 평가하는 동안 종료

많은 프로그래밍 언어는 임의의 식별자와 그 안에 표현식이있는 괄호 쌍을 구문 분석 할 수 있습니다.

identifier(1 + 1)

때로는 사용중인 다른 언어로 코드를 제공해야하기 때문에 문제의 식별자 형식이 고정 될 수 있습니다. 식별자가 언어가 실제로 가지고있는 기능과 일치하지 않으면 처음에는 문제를 일으키는 것처럼 보일 수 있습니다.

그러나 많은 프로그래밍 언어는 함수 자체가 실제로 존재하는지 (예 : Lua) 확인하기 전에 함수의 인수를 평가하므로 이러한 종류의 구문을 사용할 수 있습니다. 함수의 인수 내부에서 프로그램을 종료하기 만하면됩니다.

다음은 dc / Lua 폴리 글롯의 예입니다.

c2pq(1 + #os.exit(print(3)))

c2pq2를 인쇄하고 종료하는 dc 프로그램입니다. Lua는 이것을 함수의 이름으로보고 있지만, 인수에 exit 명령을 넣어서 Lua가 오류가 발생하는 것을 막을 수 있습니다. 이 구성의 가장 큰 장점은 할당 ( c2pq =) 과 달리 변수 이름이시길로 시작하는 언어와 자동으로 호환되지 않는다는 것입니다. 함수 이름 구문은 변수 이름 구문보다 언어에서 훨씬 더 일관성이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.