C #에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 저는 C #에 다소 특정한 코드 골프 문제에 적용 할 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.
-marcog의 아이디어에서 빌린;)
C #에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 저는 C #에 다소 특정한 코드 골프 문제에 적용 할 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.
-marcog의 아이디어에서 빌린;)
답변:
기본적으로 문자열로 안전하게 캐스트 할 수있는 숫자 및 기타 유형 에 사용 .ToString()
하는 대신 +""
.
.ToString() <-- 11 chars
+"" <-- 3 chars
(1+"").DoSomethingWith1String();
String.Concat(object)
virtual calling 대신 인수로 static 을 호출 object.ToString()
합니다. Concat
명시 적으로 null
빈 문자열 로 변환 합니다 ( 참조 소스 참조 ). 진행중인 '네이티브 캐스팅'이 없으며 이와 같은 것을 변환 할 수 있습니다. 결과는 경우에 따라 그다지 유용하지 않을 수도 있습니다! (그러나 null 동작은 잘 될 수 있습니다).
$"{n}"
한 번은 의도적으로 프로그램을 배치 namespace System
하여 특정 수업에 대한 액세스를 단축 할 수 있습니다. 비교
using System;using M=System.Math;
에
namespace System{using M=Math;
System
네임 스페이스의 항목에 대해서만 두 번 이상 호출해야하는 경우에만 유용합니다 .
using System;class P...
.
using System;
동일한 네임 스페이스의 클래스에 대한 별칭을 갖는 것이 아니라 여기에 표시된 방식보다 짧습니다.
using static System.Math;
C # 6에서는 더 짧습니다 (클래스가 아닌 마치 글로벌 한 것처럼 모든 함수를 사용할 수 있음). using static
여러 클래스에 액세스해야하는 경우 보다 원래 제안이 여전히 짧을 수 있습니다.
static
키워드는 종종 M.
메소드 호출에서 제외되는 비용보다 오래 걸리지 만 옵션입니다. 그러나 선불 비용이 많이 드는 선불 비용이 많이 듭니다.
LINQ를 사용 Select
하는 경우 람다를 만드는 대신 메서드를 직접 전달할 수 있습니다 .
그래서 대신
foo.Select(x=>int.Parse(x))
당신이 사용할 수있는
foo.Select(int.Parse)
직접.
( Timwi의 C # 답변 중 하나를 개선 할 때 최근에 발견되었습니다 .)
C #에서 가장 작은 컴파일 가능한 프로그램은 29 자입니다.
class P
{
static void Main()
{
}
}
따라서 그것을 길이에서 제거하고 시작하는 데 걸리는 양에 대한 답변을 판단하십시오. C #은 대부분의 [code-golf]
문제 의 핵심 인 입력을 인쇄하거나 읽을 때 다른 언어와 경쟁 할 수 없으므로 걱정하지 마십시오. C # 골퍼로서 당신은 언어와 경쟁하고 있습니다.
명심해야 할 몇 가지 사항 :
if
대괄호를 제거하려면 가능하면 모든 루프와 명령문을 한 줄로 줄이십시오.static int Main()
28자를 사용하여 컴파일합니다 .
return
.
대신에
bool a = true;
bool b = false;
하다
var a=0<1;
var b=1<0;
여러 변수가 필요한 경우 이것을 사용하십시오 ( @ VisualMelon 제안 )
bool a=0<1,b=!a;
bool a=0<1,b=!a;
위에 원계 조작자 선호 if
.. else
적절한 블록.
예를 들면 다음과 같습니다.
if(i<1)
j=1;
else
j=0;
보다 효율적으로 :
j=i<1?1:0;
var x = input ?? "";
(내 합체를 사랑)
i < 1
이 아닌 경우 가 있습니다. 특히 복잡한 문장이거나 이름 j
이 긴 경우가 있습니다. IMO는 부작용을 잘 전달하지 못합니다. 경우에 경우 if (i < 1)
처럼 뭔가 if (SendEmail(recipient))
부작용의 성공 여부에 따라 참 / 거짓 반환, 나는 경우 / 다음 표기법을 선호합니다.
j=i<1?1:0;
하지 않습니다.
Console.ReadLine()
코드에서 여러 번 (최소 3 회) 사용해야 하는 경우 다음을 수행 할 수 있습니다.
Func<string>r=Console.ReadLine;
그런 다음 사용하십시오
r()
대신에
()
첫 번째 줄에서 제거해야한다고 생각합니다 .
auto r=Console.ReadLine;
없습니까?
auto
는 C++
동사입니다. var
입니다 C#
. 이 작업을 수행 할 수없는 이유 Console.ReadLine
는 오버로드 되었기 때문에 컴파일러에 어떤 과부하가 필요한지 알리기 위해 함수 서명을 지정해야하기 때문입니다.
문자열 길이까지 반복하지 않고 명령 행 인수의 각 문자를 읽을 때 :
static void Main(string[]a){
for(int i=0;i<a[0].Length;)Console.Write(a[0][i++]);
}
try / catch 블록을 사용하여 문자를 저장하여 끝을 찾을 수 있습니다.
static void Main(string[]a){
try{for(int i=0;;)Console.Write(a[0][i++]);}catch{}
}
이는 다음과 같은 배열 내의 배열에 적용됩니다.
string[]
int[][]
IList<IList<T>>
C # 6에서는 람다를 사용하여 함수를 정의 할 수 있습니다.
int s(int a,int b)=>a+b;
이것은 다음과 같은 함수를 정의하는 것보다 짧습니다.
int s(int a,int b){return a+b;}
사용하는 대신:
Enumerable.Range(0,y).Select(i=>f(i))
함수의 결과에 열거 가능한을 얻을 수 f
있는 모든 위해 int
에 [0,y]
사용할 수있는
new int[y].Select((_,i)=>f(i))
당신이 필요 string
하거나 Enumerable
프로그램에서 구현 하는 것이 있다면 그것들도 사용할 수 있습니다
var s="I need this anyway";
s.Select((_,i)=>f(i))
Dictionary<TKey, TValue>
코드에서 제네릭 을 두 번 이상 사용해야하는 경우 다음 예제와 같이 사전 클래스를 선언 할 수 있습니다.
class D:Dictionary<int,string>{}
그런 다음 사용하십시오
D d=new D{{1,"something"},{2,"something else"}};
Dictionary<int,string>
모든 인스턴스화에 대해 반복 하는 대신 .
나는 이 답변 에이 기술을 사용했다
using D = System.Collections.Generic.Dictionary<int,string>;
float
및 double
리터럴을 사용하여 몇 바이트를 저장할 수 있습니다 .
var x=2.0;
var y=2d; // saves 1 byte
int
a를 반환하기 위해 산술 이 필요한 경우 float
또는 double
리터럴을 사용하여 강제로 변환 할 수 있습니다.
((float)a+b)/2; // this is no good
(a+b)/2.0; // better
(a+b)/2f; // best
캐스트해야하는 상황에 처한 경우 대신 곱셈을 사용하여 몇 바이트를 절약 할 수 있습니다.
((double)x-y)/(x*y);
(x*1d-y)/(x*y); // saves 5 bytes
(x-y)*1d/x/y;
다음과 같이 개인 또는 공용이 고유 한 위치를 기억하십시오.
class Default{static void Main()
비교하자면
public class Default { public static void Main()
Main
은 예를 들어 Java와 달리 인수가 필요하지 않습니다.
한 줄 람다 식의 경우 대괄호와 세미콜론을 건너 뛸 수 있습니다. 한 매개 변수 표현식의 경우 괄호를 건너 뛸 수 있습니다.
대신에
SomeCall((x)=>{DoSomething();});
사용하다
SomeCall(x=>DoSomething);
SomeCall(DoSomething)
더 나은
루핑 :
변수 선언 :
int max;
for(int i=1;i<max;i++){
}
지다:
int max,i=1;
for(;i<max;i++){
}
그리고 i 변수를 한 번만 필요하거나 작업 해야하는 경우 -1에서 시작하거나 (루프 환경에 따라 0) 인라인으로 증가시킬 수 있습니다.
int max,i=1;
for(;i<max;i++){
Console.WriteLine(i);
}
에
int max,i=1;
for(;i<max;){
Console.WriteLine(++i);
}
그리고 그것은 한 문자 씩 줄어들고 코드도 약간 난독 화합니다. 다음 i
과 같이 FIRST 참조 에만 그렇게하십시오 : (한 문자 최적화는 그다지 많지 않지만 도움이 될 수 있습니다)
int max,i=1;
for(;i<max;i++){
Console.WriteLine(i + " " + i);
}
에
int max,i=1;
for(;i<max;){
Console.WriteLine(++i + " " + i);
}
루프가 증가하지 않아도되는 경우 i
(역순 루프) :
for(int i=MAX;--i>0;){
Console.WriteLine(i);
}
++
그런 경우에 루프 헤더에 직접 넣습니다. for(;++i<max;)
따라서 따르기 쉽고 잘못하기가 더 어렵습니다.
for
헤더에 넣을 수 있는지 여부에 따라 문자가 다시 저장됩니다.
for(;i<max;)
합니다 while(i<max)
. 같은 바이트 수이지만 나를 위해 더 깨끗해 보입니다.
출력 매개 변수가 문자를 저장할 수있는 상황이 있습니다. 다음 은 10 핀 볼링 점수 알고리즘 인 약간 고안된 예입니다.
반품 문 :
........10........20........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150..
public double c(int[]b){int n,v,i=0,X=10;double t=0;while(i<19){n=b[i]+b[i+1];v=b[i+2];t+=(n<X)?n:X+v;if(b[i]>9)t+=b[i+(i>16|v!=X?3:4)];i+=2;}return t;}
그리고 출력 매개 변수로 :
........10........20........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......
public void d(int[]b,out double t){int n,v,i=0,X=10;t=0;while(i<19){n=b[i]+b[i+1];v=b[i+2];t+=(n<X)?n:X+v;if(b[i]>9)t+=b[i+(i>16|v!=X?3:4)];i+=2;}}
여기서 출력 매개 변수는 총 5자를 저장합니다.
정말 간단한 공간 절약 개선은 보간입니다. 대신에:
string.Format("The value is ({0})", (method >> 4) + 8)
$
식을 인라인 하는 데 사용하십시오 .
$"The value is ({(method >> 4) + 8})"
이것은 C # 6.0의 새로운 표현식 본문과 함께 간단한 문자열 계산 문제를 C #에서 꽤 골프화 할 수 있어야합니다.
i+$" bottles of beer";
이보다 짧습니다 $"{i} bottles of beer"
.
$
제외 해야합니다 .
{i}
앞에 하나와 중간에 하나를
C # 람다를 사용하십시오. PPCG는 람다 입력 / 출력을 허용하므로이를 사용해야합니다.
고전적인 C # 메소드는 다음과 같습니다.
bool Has(string s, char c)
{
return s.Contains(c);
}
람다로서
Func<string, char, bool> Has = (s, c) => s.Contains(c);
익명의 람다도 허용됩니다.
(s, c) => s.Contains(c)
모든 소음과 초점을 제거하십시오!
최신 정보:
우리는 함께 한 단계 더 향상시킬 수 있습니다 무두질 @TheLethalCoder의 주석으로 :
s => c => s.Contains(c);
@Felix Palmen의 curring 예 : WPA 키는 어떻게 계산합니까?
정확히 두 개의 매개 변수가 있으면 유용하며 비어있는 사용하지 않는 변수 _
가 더 좋습니다. 참조 이에 대한 메타 게시물을 . 이 트릭을 여기에 사용합니다 . 약간의 기능을 변경해야합니다. 예 : 온라인으로 사용해보십시오!
s=>c=>...
s=>s.Contains
.
(string s,char c)=>s.Contains(c)
클래스 이름은 한 글자 만 만드십시오. 에 강화 C #으로 코드 골프를위한 팁 우리가에서 이동
class Default{static void Main()
에
class D{static void Main()
이 경우 6 문자를 녹아웃합니다.
그만큼 Compute
인스턴스 메소드 System.Data.DataTable
는 간단한 문자열 표현식을 평가할 수 있습니다. 예 :
namespace System.Data
{
class P
{
static void Main()
{
Console.Write(new DataTable().Compute("30*2+50*5/4",""));
}
}
}
그 자체로는 "골피"는 아니지만 때로는 유용 할 수도 있습니다.
일반적으로 두 변수를 바꾸려면 임시 변수를 선언하여 값을 저장해야합니다. 다음과 같이 보일 것입니다.
var c=a;a=b;b=c;
16 바이트입니다! 더 나은 다른 교환 방법이 있습니다.
//Using tuples
(a,b)=(b,a);
//Bitwise xoring
a=a^b^(b=a);
//Addition and subtraction
a=a+b-(b=a);
//Multiplication and division
a=a*b/(b=a);
마지막 3 개는 숫자 값에 대해서만 작동하며 ASCII 전용으로 지적한 것처럼 마지막 2 개는 ArithmeticOverflow 예외를 초래할 수 있습니다. 위의 모든 것은 12 바이트이며 첫 번째 예제와 비교하여 4 바이트가 절약됩니다.
사용하다 %
꽉 결합 (다소) 제한 공제. 이렇게하면 빼기 주위에 괄호 쌍을 저장할 수 있으며 그 결과 곱하기 또는 나누기를 원할 수 있습니다. 그러나 심각한 제한이 있습니다.
대신에
char b='5'; // b is some ASCII input
int a=(b-48)*c; // we want to find the numerical value of b, and multiply it by something ('0'==48)
치다
char b='5'; // b is some ASCII input
int a=b%48*c; // only good for ASCII within 48 of '0' (positive only)!
예 :
'5'%'0'*2 -> 10
'5'%'0'*-1 -> -5
'5'%'0'/2 -> 2
방금 이것을 발견했으며 앞으로 ASCII 작업을 할 때마다 기억해야 할 것이 가치 있다고 생각합니다. (나는 현재 소형 숫자 표현을 위해 ASCII를 사용하는 곳에서 골프를 치고 있지만 다른 조건 을 곱 1
하거나 -1
다른 조건 과이 스트라이프 2 바이트를 기반으로 해야 합니다)
using
모두 동일한 계층 구조에서 벗어나는 여러을 포함 해야하는 경우 가장 긴 계층을 다음과 같이 사용하는 것이 더 짧습니다 namespace
.
using System;
using System.Linq;
//Some code
vs :
namespace System.Linq
{
//Some code
}
골프 코드를 향상시키면서 오늘 밤 "트렌치에서"발견했습니다. 처리 할 클래스가 있으면 생성자에서 작업을 수행하여 메소드 선언을 저장할 수 있습니다.
콘솔 응용 프로그램을 줄이면서 이것을 발견했습니다. static void Main()
. 모든 함수와 변수는 정적으로 선언해야했습니다. 생성자에서 수행 된 주요 작업으로 멤버 함수 및 변수가 포함 된 중첩 클래스를 만들었습니다. 이것은 또한 호출 코드에 문자를 저장합니다.
예를 들어 메소드가있는 클래스 :
class a
{
public void b()
{
new c().d("input");
}
}
class c
{
public void d(string e)
{
System.Console.Write(e.Replace("in", "out"));
}
}
생성자에서 작업하는 클래스 :
class a
{
public void b()
{
new c("input");
}
}
class c
{
public c(string e)
{
System.Console.Write(e.Replace("in", "out"));
}
}
이 예는 9자를 저장합니다.
Action
like Func
를 사용하여 함수를 변수로 설정 하십시오 . Action
아무것도 반환하지 void
않으므로 인쇄하기에 좋습니다.
예를 들면 다음과 같습니다.
Action<string>w=Console.WriteLine;
w("Hello World");
이 팁은 @ W0lf 와 함께 사용하는 훌륭한 예에서Func
ReadLine
영감을 받았습니다 .
여러 개의 빈 / 일치하는 문자열을 선언해야하는 경우 다음을 사용하여 몇 바이트를 저장할 수 있습니다.
string a="";string b="";string c=""; // 36 bytes
var a="";var b="";var c=""; // 27 bytes
string a="",b="",c=""; // 22 bytes
string a="",b=a,c=a; // 20 bytes
불행하게도 var a="",b=a,c=a;
같은 불법implicitly type variable cannot have multiple declarators
var a=b=c=""
자바 스크립트처럼 할 수 있습니까 ?