C #에서 코드 골프 팁


62

C #에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 저는 C #에 다소 특정한 코드 골프 문제에 적용 할 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.

-marcog의 아이디어에서 빌린;)


BEST TIP => 챌린지에 가장 긴 답변을 제출하지 않으려면 .NET 이외의 것을 사용하십시오. .NET은 매우 장황하며 IDE가 타이핑을하도록 설계되었습니다. IDE 버팀목이있는 한 일반 프로그래밍에서 들리는 것처럼 실제로 나쁜 것은 아니지만 코드 골프에서는 전략이 실패합니다.
krowe

달력 사진을 용서해주세요. 짧은 통지로 찾을 수있는 전부였습니다.
undergroundmonorail

답변:


59

기본적으로 문자열로 안전하게 캐스트 할 수있는 숫자 및 기타 유형 에 사용 .ToString()하는 대신 +"".

.ToString() <-- 11 chars
+""         <--  3 chars

5
이것은 JS에서도 작동합니다.
Cyoce

1
중괄호를 포함하기 위해 나중에 문자열을 사용해야하는 경우 일반적으로 실제로 5 자입니다.(1+"").DoSomethingWith1String();
TheLethalCoder

1
문자열이 필요한 경우 일반적으로 문자열을 저장합니다. 다른 사용법은 기본적으로 ToString ()을 유추 할 수 있습니다.
jcolebrand

1
이것은 실제로 String.Concat(object)virtual calling 대신 인수로 static 을 호출 object.ToString()합니다. Concat명시 적으로 null빈 문자열 로 변환 합니다 ( 참조 소스 참조 ). 진행중인 '네이티브 캐스팅'이 없으며 이와 같은 것을 변환 할 수 있습니다. 결과는 경우에 따라 그다지 유용하지 않을 수도 있습니다! (그러나 null 동작은 잘 될 수 있습니다).
VisualMelon

1
대안- 문자열 보간 :$"{n}"
Andriy Tolstoy

41

한 번은 의도적으로 프로그램을 배치 namespace System하여 특정 수업에 대한 액세스를 단축 할 수 있습니다. 비교

using System;using M=System.Math;

namespace System{using M=Math;

9
한 번의 사용으로 문제를 해결할 때 클래스 / 함수를 완전히 규정하는 것이 좋습니다. 이것은 System네임 스페이스의 항목에 대해서만 두 번 이상 호출해야하는 경우에만 유용합니다 .
Nick Larsen

당신은 또한 할 수 있습니다 using System;class P....
ldam

@Logan : 이것은 using System;동일한 네임 스페이스의 클래스에 대한 별칭을 갖는 것이 아니라 여기에 표시된 방식보다 짧습니다.
Joey

using static System.Math;C # 6에서는 더 짧습니다 (클래스가 아닌 마치 글로벌 한 것처럼 모든 함수를 사용할 수 있음). using static여러 클래스에 액세스해야하는 경우 보다 원래 제안이 여전히 짧을 수 있습니다.
우유

@milk : 추가 static키워드는 종종 M.메소드 호출에서 제외되는 비용보다 오래 걸리지 만 옵션입니다. 그러나 선불 비용이 많이 드는 선불 비용이 많이 듭니다.
Joey

30

사용 var선언 및 유형에 문자를 저장 (단일) 변수를 초기화 :

string x="abc";

된다

var x="abc";

int물론에 필요한 것은 아닙니다 .


2
그 기억 var예를 들어, 여러 선언자를 가질 수 없습니다 var x="x",y="y";수 없습니다.
Ian H.

29

LINQ를 사용 Select하는 경우 람다를 만드는 대신 메서드를 직접 전달할 수 있습니다 .

그래서 대신

foo.Select(x=>int.Parse(x))

당신이 사용할 수있는

foo.Select(int.Parse)

직접.

( Timwi의 C # 답변 중 하나를 개선 할 때 최근에 발견되었습니다 .)


2
FWITW 이것을 η- 감소
ThreeFx


5
더 실용적으로, 그것은 짧습니다 : -þ
Joey

23

C #에서 가장 작은 컴파일 가능한 프로그램은 29 자입니다.

class P
{
    static void Main()
    {   
    }
}

따라서 그것을 길이에서 제거하고 시작하는 데 걸리는 양에 대한 답변을 판단하십시오. C #은 대부분의 [code-golf]문제 의 핵심 인 입력을 인쇄하거나 읽을 때 다른 언어와 경쟁 할 수 없으므로 걱정하지 마십시오. C # 골퍼로서 당신은 언어와 경쟁하고 있습니다.

명심해야 할 몇 가지 사항 :

  • if대괄호를 제거하려면 가능하면 모든 루프와 명령문을 한 줄로 줄이십시오.
  • stdin과 command line 사이에 옵션이 주어지면 항상 command line을 사용하십시오!

)이 보통뿐만 아니라 원을 포함 않습니다
jcolebrand

1
As a C# golfer, you're really competing against the language 믿을 수
없을 정도로

1
사실, 그것은 사실이 아닙니다. 또한 static int Main()28자를 사용하여 컴파일합니다 .
Metoniem


21

대신에

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;
VisualMelon

18

위에 원계 조작자 선호 if.. else적절한 블록.

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

if(i<1)
    j=1;
else
    j=0;

보다 효율적으로 :

j=i<1?1:0;

15
나는 두 번째 경우가 일반적으로 이와 같은 것들에 대해 본질적으로 더 읽기 쉽다고 생각하는 유일한 사람입니까? 나는 그것을 일상적으로한다. 나는 내가 좋아하는 일을 할 (문자열에 같은) 널 조건을 방지하기 위해 필요한 경우 또한, var x = input ?? "";(내 합체를 사랑)
jcolebrand

더 읽기 쉬운 옵션 i < 1이 아닌 경우 가 있습니다. 특히 복잡한 문장이거나 이름 j이 긴 경우가 있습니다. IMO는 부작용을 잘 전달하지 못합니다. 경우에 경우 if (i < 1)처럼 뭔가 if (SendEmail(recipient))부작용의 성공 여부에 따라 참 / 거짓 반환, 나는 경우 / 다음 표기법을 선호합니다.
Nick Larsen

11
두 번째 경우에는 괄호가 필요 j=i<1?1:0;하지 않습니다.
Danko Durbić

3
이 질문은 C #에 특정한 팁을 요구합니다. 이것은 모든 언어팁에 포함 된 것 중 하나 입니다.
피터 테일러

4
@PeterTaylor 3 년 전에이 질문에 답변했습니다. 연결 한 스레드가 생성되기 훨씬 전에
Nellius

15

사용의 효과적인 사용

대신하여 float (의 별칭 인 System.Single)을 z사용할 수 있습니다.z=System.Single;

그리고 교체 z=System.Single;z=Single;네임 스페이스에서 프로그램을 배치하여 System. (Joey의 답변과 마찬가지로)

이것은 다른 값 유형 (별칭 인 것을 사용하십시오), 구조체 및 클래스에 적용 할 수 있습니다


14

Console.ReadLine()코드에서 여러 번 (최소 3 회) 사용해야 하는 경우 다음을 수행 할 수 있습니다.

Func<string>r=Console.ReadLine;

그런 다음 사용하십시오

r()

대신에


()첫 번째 줄에서 제거해야한다고 생각합니다 .
mellamokb

@mellamokb 맞습니다, 감사합니다! 결정된.
Cristian Lupascu

1
당신은 할 수 auto r=Console.ReadLine;없습니까?
Claudiu

2
@claudiu no, 불행히도 ideone.com/jFsVPX
Cristian Lupascu

@Claudiu autoC++동사입니다. var입니다 C#. 이 작업을 수행 할 수없는 이유 Console.ReadLine는 오버로드 되었기 때문에 컴파일러에 어떤 과부하가 필요한지 알리기 위해 함수 서명을 지정해야하기 때문입니다.
GreatAndPowerfulOz

14

문자열 길이까지 반복하지 않고 명령 행 인수의 각 문자를 읽을 때 :

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>>

7
정말 끔찍한 일입니다 ... 사랑합니다!
Alex Reinking

이런 쓰레기는 천재입니다. 실제로 배열을 반복하면서 캐릭터를 저장했습니다
Gaspa79

이것은 정말 악하다!
GreatAndPowerfulOz

13

C # 6에서 람다를 사용하여 함수 정의

C # 6에서는 람다를 사용하여 함수를 정의 할 수 있습니다.

int s(int a,int b)=>a+b;

이것은 다음과 같은 함수를 정의하는 것보다 짧습니다.

int s(int a,int b){return a+b;}

3
C # 6은 완전히 새로운 코드 골프 기능을 제공합니다
jcolebrand

C # 7에서는 다른 함수 내에서 로컬 함수를 만들 수 있습니다. 골프를 타는 동안 도움이 될지 의심 스럽지만 여전히 알기 쉬운 방법입니다.
TehPers

1
그것은 공식적으로 람다가 아닙니다. 그것은이다 표현의 몸체 멤버 .
재귀

13

LINQ

사용하는 대신:

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))

나는 샤미르의 비밀 공유 도전에 대한 대답 에이 트릭을 사용합니다 .
aloisdg

최적화를 사용하여 ienumerable을 반복하지 않으면 문자열 부분이 실행될 것이라고 생각하지 않습니다. 내가 .ToArray (); 할 때까지 실패했습니다. 그 외에는 놀라운 팁!
Gaspa79

네 열거 형은 게으르지 만 문자열이있는 세 가지 예제가 아니라 세 가지 예제 모두에 해당됩니다.
raggy

11

Dictionary<TKey, TValue>코드에서 제네릭 을 두 번 이상 사용해야하는 경우 다음 예제와 같이 사전 클래스를 선언 할 수 있습니다.

class D:Dictionary<int,string>{}

그런 다음 사용하십시오

D d=new D{{1,"something"},{2,"something else"}};

Dictionary<int,string>모든 인스턴스화에 대해 반복 하는 대신 .

나는 이 답변 에이 기술을 사용했다


2
또한 "var d"대신 "D d"
Zukki

@Zukki 분명히! 내가 무엇을 생각하고 있었습니까? :)
Cristian Lupascu

대안 :using D = System.Collections.Generic.Dictionary<int,string>;
Andriy Tolstoy

10

floatdouble리터럴을 사용하여 몇 바이트를 저장할 수 있습니다 .

var x=2.0;
var y=2d;         // saves 1 byte

inta를 반환하기 위해 산술 이 필요한 경우 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;
재귀

9

다음과 같이 개인 또는 공용이 고유 한 위치를 기억하십시오.

class Default{static void Main()

비교하자면

public class Default { public static void Main()

5
그리고 항상 수업을 한 글자 만 만드십시오 :-)
Joey

2
아, 그리고 여기에 암시 된 또 다른 좋은 점 Main은 예를 들어 Java와 달리 인수가 필요하지 않습니다.
Joey

@Joey : 그리고 공개 할 필요도 없습니다.
R. Martinho Fernandes

1
@martinho ~ 내 대답을 읽었습니까? ;) main on public
jcolebrand

@Joey ~ 나는 게시물 당 하나를 유지하려고 노력했다. 다른 사람이없는 것으로 보아서 계속 추가하겠습니다.
jcolebrand

9

한 줄 람다 식의 경우 대괄호와 세미콜론을 건너 뛸 수 있습니다. 한 매개 변수 표현식의 경우 괄호를 건너 뛸 수 있습니다.

대신에

SomeCall((x)=>{DoSomething();});

사용하다

SomeCall(x=>DoSomething);

11
나는 생산 코드에서도 1 매개 변수 람다에 대한 괄호를 쓰지 않습니다.
R. Martinho Fernandes 2012

가독성을 위해 람다를 여러 줄로 나누는 것을 좋아하기 때문에 항상 대괄호를 사용합니다.
Juliana Peña

2
SomeCall(DoSomething)더 나은
GreatAndPowerfulOz

9

루핑 :

변수 선언 :

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;)따라서 따르기 쉽고 잘못하기가 더 어렵습니다.
Joey

@Joey 이러한 경우 나는 같은 길이이지만 읽기 쉬운 while (++ i <max)로 전환하는 경향이 있습니다.
ICR

ICR : 다른 (이전) 문을 for헤더에 넣을 수 있는지 여부에 따라 문자가 다시 저장됩니다.
Joey

a1 바이트 절약을 위해 두 선언 모두 for 절로 다시 이동할 수 있습니다.
재귀

로 변경하는 것을 좋아 for(;i<max;)합니다 while(i<max). 같은 바이트 수이지만 나를 위해 더 깨끗해 보입니다.
Ayb4btu

8

출력 매개 변수가 문자를 저장할 수있는 상황이 있습니다. 다음 은 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자를 저장합니다.


8

C #에서는 짝수 if(n%2)인지 확인하는 n것이 허용되지 않습니다 . 그렇게하면을 얻습니다 cannot implicity convert int to bool. 순진한 처리는 다음과 같습니다.

if(n%2==0)

더 좋은 방법은 다음을 사용하는 것입니다.

if(n%2<1)

나는 이것을 1 바이트를 얻기 위해 사용 했다 .

-1%2==-1이 방법으로도 고려 되므로 양수에만 적용됩니다.


6

문자열 보간

정말 간단한 공간 절약 개선은 보간입니다. 대신에:

string.Format("The value is ({0})", (method >> 4) + 8)

$식을 인라인 하는 데 사용하십시오 .

$"The value is ({(method >> 4) + 8})"

이것은 C # 6.0의 새로운 표현식 본문과 함께 간단한 문자열 계산 문제를 C #에서 꽤 골프화 할 수 있어야합니다.


3
또한 i+$" bottles of beer";이보다 짧습니다 $"{i} bottles of beer".
aloisdg

1
@aloisdg하지만 첫 번째 경우에는 $제외 해야합니다 .
Metoniem

@Metoniem 참으로! 내 원래의 경우 {i}앞에 하나와 중간에 하나를
두었

@aloisdg 아, 알겠습니다. 네, 부끄러운 코멘트는 편집 할 수 없습니다 :(
Metoniem

6

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 키는 어떻게 계산합니까?

정확히 두 개의 매개 변수가 있으면 유용하며 비어있는 사용하지 않는 변수 _가 더 좋습니다. 참조 이에 대한 메타 게시물을 . 이 트릭을 여기에 사용합니다 . 약간의 기능을 변경해야합니다. 예 : 온라인으로 사용해보십시오!


1
그것이 팁의 다른 곳에 있는지 확실하지 않지만이 예제에서는 카레도 사용할 수 있습니다.s=>c=>...
TheLethalCoder

@TheLethalCoder 실제로 우리는 할 수 있습니다! 답변 감사합니다 업데이트합니다!
aloisdg

이 경우 에타 감소를 사용할 수 있습니까? 이와 같은 것 : s=>s.Contains.
corvus_192

'유형화되지 않은 람다'품종의 C # 및 Java 답변은 좋아지지 않습니다. 이 메타 게시물 에 대한 토론에 참여하고 싶을 수도 있습니다 . 제안 된 대안은 다음과 같습니다(string s,char c)=>s.Contains(c)
VisualMelon




5

두 변수 교환

일반적으로 두 변수를 바꾸려면 임시 변수를 선언하여 값을 저장해야합니다. 다음과 같이 보일 것입니다.

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 바이트가 절약됩니다.


그러나 숫자에만 적용되며 심지어 튜플 및 xor 이외의 정수 한계에 도달 할 때도 이것을 정수에 적용합니다. 때때로 다른 숫자 유형도 한계에 도달합니다.
ASCII 전용

4

LinqPad를 사용하면 명령문을 직접 실행할 수 있으므로 모든 프로그램 오버 헤드를 제거 할 수 있습니다. (그리고 codegolf에서는 완전히 합법적이어야합니다 ... 아무도 .exe가 필요하다고 말하지 않습니다)

.Dump()확장 방법을 사용하여 출력됩니다 .


.NetFiddle 지원 .Dump();)
aloisdg

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 바이트를 기반으로 해야 합니다)


4

using모두 동일한 계층 구조에서 벗어나는 여러을 포함 해야하는 경우 가장 긴 계층을 다음과 같이 사용하는 것이 더 짧습니다 namespace.

using System;
using System.Linq;
//Some code

vs :

namespace System.Linq
{
    //Some code
}

3

골프 코드를 향상시키면서 오늘 밤 "트렌치에서"발견했습니다. 처리 할 클래스가 있으면 생성자에서 작업을 수행하여 메소드 선언을 저장할 수 있습니다.

콘솔 응용 프로그램을 줄이면서 이것을 발견했습니다. 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자를 저장합니다.



3

빈 문자열 / 일치하는 문자열을 함께 선언

여러 개의 빈 / 일치하는 문자열을 선언해야하는 경우 다음을 사용하여 몇 바이트를 저장할 수 있습니다.

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=""자바 스크립트처럼 할 수 있습니까 ?
corvus_192

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