Clean에서 골프를 치기 위해 어떤 일반적인 팁이 있습니까? 일반적으로 코드 골프 문제에 적용 할 수 있고 최소한 Clean에 특정한 아이디어 만 게시하십시오.
Clean에 대해 들어 본 적이 없다면 여기 에서 더 자세히 알아볼 수 있습니다 .
또는 대화방에 참여할 수 있습니다 .
답변
import StdEnv
가능하면 피하십시오
액세스에 내장 된 기능도 겉으로는 기본 것과 같은 (==)
나 map
, import 문은 일반적으로 필요하다 import StdEnv
는 가장 일반적인 모듈처럼 수입하기 때문에 StdInt
, StdBool
등 (참조 여기에 더 많은 정보에 대한 StdEnv
).
그러나 일부 문제의 경우 이러한 가져 오기를 피하고 목록 이해 및 패턴 일치와 같은 핵심 언어 기능을 사용할 수 있습니다.
예를 들어
import StdEnv
map f list
하나는 쓸 수있다
[f x\\x<-list]
대안 목록 :
필요한 일부 함수 또는 함수 호출 import StdEnv
, 가져 오기가 필요없는 대안 및 대략적인 바이트 추정값 저장.
hd
->(\[h:_]=h)
, ~ 6 바이트tl
->(\[_:t]=t)
, ~ 6 바이트map f list
->[f x\\x<-list]
, ~ 10 바이트filter p list
->[x\\x<-list|p x]
, ~ 11 바이트(&&)
->%a b|a=b=a;%
, ~ 6 바이트(||)
->%a b|a=a=b;%
, ~ 6 바이트not
->%a|a=False=True;%
, ~ 1 바이트and
->%[a:r]|a= %r=a;%_=True
, ~ 0 바이트or
->%[a:r]|a=a= %r;%_=False
, ~ 0 바이트
직접 대체는 가져 오기보다 더 많은 바이트를 생성하기 때문에 마지막 몇 개는 실제로 바이트를 절약 할 수 없지만 목록에 대한 재귀가 필요한 경우 가능할 수 있습니다.
답변
언어를 배우는 방법을 알고
결국, 사람들은 어떻게 사용할 수없는 언어로 골프를 칠 수 있습니까!
온라인
Clean은 잘 알려 지거나 문서화 된 언어가 아니며, 그 이름으로 인해 이러한 문제를 해결하는 데 필요한 리소스를 쉽게 찾을 수 없습니다.
Clean은 원래 Concurrent Clean 이라고 하며 Clean과 관련된 거의 모든 문서의 서문에서 여전히 사용됩니다. 따라서 Clean을 찾는 경우에는 Concurrent Clean을 찾으십시오.
Clean과 Haskell의 더 큰 유사점 중 하나는 Clean 과 함께 제공되는 라이브러리를 다루는 함수 검색 엔진 인 Cloogle 의 존재입니다 .
토지 상에서
Clean과 함께 제공되는 라이브러리는 적절하게 주석 처리되고 다소 자체 문서화 된 Clean 소스 파일 형식이며 IDE를 사용하여 찾아 볼 수 있습니다.
(또한 전체 예제 프로그램과 함께 제공됩니다 $INSTALL/Examples
.)
말하자면, Windows 버전의 Clean에는 IDE가 포함되어 있습니다. 현대 표준에 의해 상당히 제한적이지만 텍스트 편집기와 명령 줄을 사용하는 것보다 세상이 더 좋습니다.
학습의 맥락에서 가장 유용한 두 가지 기능은 다음과 같습니다.
- 오류를 두 번 클릭하여 어느 줄에 있는지 확인할 수 있습니다
- 모듈 이름을 강조 표시하고을 눌러
[Ctrl]+[D]
정의 파일을 열거 나 (또는[Ctrl]+[I]
구현 파일에 사용) 다음 을 사용하여 정의 파일 과 구현 파일 간을 전환 할 수 있습니다.[Ctrl]+[/]
답변
문자 인코딩 잊어 버려
Clean의 컴파일러는 소스 파일을 저장 한 인코딩, 파일의 바이트 값에 대해서는 신경 쓰지 않습니다. 이것은 몇 가지 깔끔한 결과를 가져옵니다.
소스 코드 본문에는에 대한 것 외에도 인쇄 가능한 ASCII 문자에 해당하는 코드 포인트가있는 바이트 만 허용됩니다 \t\r\n
.
리터럴 :
에서는 String
하고 [Char]
리터럴 ( "stuff"
및 ['stuff']
각각), 0 바이트를 제외한 그 경고와 함께 사용할 수 있습니다 "
및 '
(대한 이스케이프해야 String
하고 [Char]
각각), 그리고 줄 바꿈과 carraige 반환 해야한다 로 대체 \n
하고 \r
(도 각각).
에서 Char
리터럴, 0을 제외한 모든 바이트는 그 의미 허용된다 :
'\n'
'
'
동일하지만 두 번째는 1 바이트 더 짧습니다.
탈출 :
표준 문자 이스케이프 \t\r\n
(등) 등을 제외하고 Clean의 모든 비 숫자 이스케이프 시퀀스는 슬래시이거나 이스케이프가 포함 된 리터럴을 구분하는 데 사용되는 인용 부호입니다.
숫자 이스케이프 시퀀스의 경우 숫자는 3 자리 숫자 다음에 끝나는 8 진수 값으로 처리됩니다. 이 수단은 문자 뒤에 널 원한다면 것을 1
A의를 String
, 사용해야하는 "\0001"
(또는 "\0\61"
) 및 없습니다 "\01"
. 당신은 아무것도 탈출을 따를 경우, 하지만, 숫자, 당신은 앞에 0을 생략 할 수 있습니다.
결과 :
Clean이 소스 파일을 처리하는 방법에 대한이 문제는 인덱스 저장 (물론 최대 255 개)과 같이 코드-골프에 여러 용도로 사용되는 기본 -256 단일 숫자 숫자의 시퀀스를 허용 String
하고 ['Char']
효과적으로 만들 수 있습니다 .
답변
기호가있는 이름 함수
함수를 정의 할 때 !@$%^&*~-+=<:|>.?/\
식별자 사이에 공백을 생략 할 수 있으므로 영숫자 문자를 사용 하는 것보다 일부 조합을 사용하는 것이 더 짧은 경우가 많습니다 .
예를 들어 : ?a=a^2
가보다 짧고 f a=a^2
호출하는 것도 짧습니다.
그러나 :
함수 식별자가 다른 심볼에 인접하여 사용되는 경우 다른 심볼 이지만 유효한 식별자를 결합하여 결합 할 수있는 경우 모두 하나의 식별자로 구문 분석되며 오류가 표시됩니다.
예를 들면 다음 ?a+?b
과 같습니다.? a +? b
또한 :
Clean에서 가져온 식별자를 덮어 쓸 수 있으므로 아직 사용되지 않은 유일한 단일 문자 기호 식별자 StdEnv
는 @$?
입니다. ^-+
더 많은 기호 식별자가 필요한 경우 덮어 쓰기 등이 유용 할 수 있지만 사용중인 식별자를 덮어 쓰지 않도록주의하십시오.
답변
K 노드를 알고
기능적 언어에서 가장 강력한 구조 (골프 용)는 다음과 같습니다 let ... in ...
.
물론 깨끗하고, 더 좋은 점이 #
있습니다.
노드 란 무엇입니까?
Clean #
과 유비쿼터스 |
(pattern guard)는 모두 ‘노드 표현’으로 알려져 있습니다.
특히, 그들은 당신이 imperatively- 프로그램 할 수 흉내 청소에 (여기 정말 좋다!).
#
(렛 전) :
둘 다 문자열로 주어진 정수 값과 그 문자의 합을 곱한 값을 계산합니다.
f s=let i=toInt s;n=sum[toInt c\\c<-:s]in n*i
f s#i=toInt s
#s=sum[toInt c\\c<-:s]
=s*i
버전이 얼마나 #
짧은 지, 어떻게 재정의 할 수 있는지 확인하십시오 s
. 변수를받을 때 가지고있는 값이 필요하지 않은 경우에 유용하므로 이름을 재사용 할 수 있습니다. ( let
그렇게하면 문제가 생길 수 있습니다)
그러나 let
다음과 같은 것이 필요할 때 사용 이 더 쉽습니다.flip f = let g x y = f y x in g
|
(패턴 가드) :
Clean의 패턴 가드는 다른 많은 기능 언어의 언어와 마찬가지로 사용할 수 있지만 명령형처럼 사용할 수도 있습니다 if ... else ...
. 그리고 삼항식의 짧은 버전.
예를 들어, 모두 정수의 부호를 반환합니다.
s n|n<>0|n>0=1= -1
=0
s n=if(n<>0)if(n>0)1(-1)0
s n|n>0=1|n<0= -1=0
물론 가드를보다 전통적으로 사용하는 마지막 것이 가장 짧지 만 첫 번째는 중첩 할 수 있음을 보여줍니다 (그러나 레이아웃 규칙에서 두 줄의 무조건 반환 절 만 동일한 줄에 나타날 수 있음). 첫 번째는 논리적으로 수행합니다.
노트:
이 표현식은 기본적으로 어디서나 사용할 수 있습니다. 람다에서, case ... of
, let ... in
, 등
답변
당신이 사용하는 경우 String
사용해야합니다Text
문자열로의 변환 및 문자열의 조작 ( 종류가 아닌 {#Char}
/ 종류)은 상당히 길고 골프에 좋지 않습니다. 그만큼String
[Char]
Text
모듈 요법이.
변환:
Text
정의 된 <+
두 가지 유형 의 연산자 를 toString
정의합니다.
이 연산자 는 최소한 19 바이트를 절약 a<+b
하는 것과 같습니다 . 추가 가져 오기를 포함 시켜서 한 번만 사용 하더라도 여전히 14 바이트를 절약합니다!toString a+++toString b
,Text
시장 조작:
Text
에서 누락 된 몇 가지 문자열 조작 스테이플을 정의합니다 StdEnv
.
+
문자열 의 연산자+++
( 보다StdEnv
)indexOf
-1
대신 C와 같은 동작이 반환 됩니다.Nothing
실패concat
문자열 목록을 연결합니다.join
구분자 문자열을 사용하여 문자열 목록을 조인합니다.split
문자열을 하위 문자열의 문자열 목록으로 분할합니다.
답변
짧은 람다 사용
때로는 람다 식을 사용하여 자신을 찾으십시오 ( map
또는 sortBy
, 등 으로 전달 ). 이 작업을 수행 할 때 (람다 작성) 할 수있는 방법이 많이 있습니다.
옳은 길:
이것은 sortBy
가장 긴 것에서 가장 짧은 것까지 관용적 람다 정렬 목록이 있습니다.
sortBy (\a b = length a > length b)
다른 올바른 방법 :
를 사용하는 경우 Data.Func
에도 할 수 있습니다
sortBy (on (>) length)
짧은 방법 :
이것은 동일하지만 골퍼 구문
sortBy(\a b=length a>length b)
다른 방법:
컴포지션 사용은 이번에는 짧지 않지만 때로는 짧을 수 있습니다.
sortBy(\a=(>)(length a)o length)
다른 방법 :
여기에 약간 고안되어 있지만 람다에서 경비원을 사용할 수 있습니다
sortBy(\a b|length a>length b=True=False)
또한 노드 이전 식
sortBy(\a b#l=length
=l a>l b)
노트:
람다에는 두 가지 형태가 더 (\a b . ...)
있으며 (\a b -> ...)
, 후자는 =
변형 과 동일 하며 , 후자는 변형 과 동일 하며 종종 람다를 정의하는 대신 무언가의 속성에 액세스하려고하는 것처럼 보입니다. 사용하지 마십시오.