Tarmo'nun ascii baskı dili, 46 bayt. (Rekabetsiz)
1 /\| /_/\|/__\_\2 \__|/ 0n{n-a-1{~}1a{2#1}$}
Sadece CJam gibi garip programlama dillerine bakarak, beni daha önce hiç kimsenin gitmediği yerlere cesaretle gitmek istediğim ve kendi dilimi icat etmek istediğim için ne kadar karmaşık, doğal olmayan ve şifreli bir dilin olabileceğini biraz şaşırtıyor. Sonuç olarak ascii desen baskısı için kendi dilimi oluşturdum.
Temel fikir, ilk pateni tanımlayabilmeniz ve sonra da basabilmenizdir - aynı tür '1' veya '2' karakterini kullanarak veya herhangi bir sayıyı kullanarak - kendi baskı düzeninizi tanımlayabilirsiniz.
Desen tanımlandıktan sonra (Numaradan numara sonuna kadar başlar) - sonraki numaralar desen yazdırmayı gerçekleştirir.
Örneğin
1 /\| /_/\|/__\_\01
Bunun gibi çıktılar:
/\
/_/\
/__\_\
Desen 1'i tanımlayacak ve hemen yazdıracaktır. Desen '|' ile ayrılan her şey olarak tanımlanır karakter. 0 sonunda - desen sonlandırma gibi davranır.
'$' Gibi özel karakterler satır besleme olarak ayrılmıştır ve '~' belirli kalıbın yarısı - aralığı için ayrılmıştır.
1 /\| /_/\|/__\_\01$~11$~1~11
Böyle bir metni çıktılar:
/\
/_/\
/__\_\
/\
/_/\
/__\_\
/\
/_/\
/__\_\
Sıradaki döngüler için geçerli. Bunun kolayca görülebilmesi gerekiyor - bu yüzden döngüler için {} braketlerini tuttum, ancak değişken isimleri otomatik olarak adlandırılmış - yani ilk braket 'a' değişkeni, ikinci 'b' ve benzerlerini kullanacak. Yineleme her zaman 0'dan belirli sayıya gider - ve bu sayı {} parantezinden önce tanımlanır.
'n' tüm fonksiyon girişi için değişkendir.
Yani kod:
1 /\| /_/\|/__\_\0n{1$}
Çıktılar (n == 4 ile):
/\
/_/\
/__\_\
/\
/_/\
/__\_\
/\
/_/\
/__\_\
/\
/_/\
/__\_\
Ve '#', trim lead boşlukları için özel değiştiricidir.
Ve sonunda bütün çözüm:
DrawPatterns.cs:
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.CSharp;
class DrawPatterns
{
//Command line parameters - for example like this: "1 /\| /_/\|/__\_\2 \__|/ 0n{n-a-1{~}1a{2#1}$}" 3
static Dictionary<char, String[]> patterns = new Dictionary<char,string[]>();
static string Tabs(int n)
{
if( n < 0 ) n = 0;
String r = "";
for( int i = 0; i < n ; i++ )
r += " ";
return r;
}
static int[] left = new int[10];
static int top = Console.CursorTop;
static int lastTop = Console.CursorTop;
static public void DoPrint(char c, char modifier = ' ')
{
if (c == '$')
{
for (int i = 0; i < left.Length; i++)
left[i] = 0;
top = lastTop + 1;
return;
}
if (!patterns.ContainsKey(c))
return;
if (modifier == '½' || modifier == '~')
{
int maxSize = patterns[c].Select(x => x.Length).Max();
for( int i = 0; i < left.Length; i++ )
left[i] += maxSize / 2;
return;
}
int iLine = 0;
foreach (var l in patterns[c])
{
Console.SetCursorPosition(left[iLine], top + iLine);
if( top + iLine > lastTop )
lastTop = top + iLine;
String s = l;
if (modifier == '#')
s = s.TrimStart(' ');
Console.WriteLine(s);
left[iLine] += s.Length;
iLine++;
}
}
static void Main(string[] _args)
{
List<String> args = _args.ToList();
String todo = "";
String code = "";
char nextVar = 'a';
String lf = "\r\n";
int align = 1;
char lastModifier = ' ';
int nextArg = 1;
Dictionary<String, String> argValues = new Dictionary<string,string>();
bool bDebug = false;
if (args.Count != 0 && args[0].ToLower() == "-d")
{
bDebug = true;
args.RemoveAt(0);
}
if (args.Count == 0)
{
Console.WriteLine("Usage: DrawPatterns.cs [options] \"script\" <arguments to script>");
Console.WriteLine("[options] allowed:");
Console.WriteLine("-d - debug");
return;
}
String prog = args[0];
for( int i = 0; i < prog.Length; i++ )
{
char c = prog[i];
// Define pattern.
if (c >= '0' && c <= '9' && !patterns.ContainsKey(c))
{
String p = Regex.Match(prog.Substring(i + 1), "[^0-9]*").Groups[0].Value;
patterns[c] = p.Split('|');
i += p.Length;
if( prog[i + 1] == '0' ) i++;
continue;
}
String procRemain = prog.Substring(i);
// modifier specified, but pattern number is not provided - use first pattern.
if( lastModifier != ' ' && ( c < '0' || c > '9' ) )
{
code += Tabs(align);
code += "print('1' , '" + lastModifier + "');" + lf;
lastModifier = ' ';
}
switch ( c )
{
case '{':
code += Tabs(align);
code += "for ( int " + nextVar + " = 0; " + nextVar + " < " + todo + " ; " + nextVar + "++ )" + lf;
// Check for all variable names if they can be used in program.
foreach ( var m in Regex.Matches(todo, "[a-zA-Z_][a-zA-Z0-9_]*", RegexOptions.Singleline) )
{
String varName = m.ToString();
if( varName.Length == 1 && varName[0] <= nextVar )
// Already declared as a loop.
continue;
if( argValues.ContainsKey(varName ) )
continue;
if( nextArg >= args.Count )
{
Console.WriteLine("Insufficient parameters provided to script - argument '" + varName + "' value is needed");
return;
}
argValues[varName] = args[nextArg];
nextArg++;
}
code += Tabs(align);
code += "{" + lf;
nextVar++;
todo = "";
align++;
break;
case '}':
align--;
code += Tabs(align);
code += "}" + lf;
break;
default:
if (((c >= '0' && c <= '9') || c == '<' || c == '$') && todo == "")
{
code += Tabs(align);
code += "print('" + c + "' , '" + lastModifier + "');" + lf;
lastModifier = ' ';
continue;
}
if (c == '½' || c == '~' || c == '#')
{
lastModifier = c;
continue;
}
if( c == '\r' || c == '\n' )
continue;
todo += c;
break;
}
} //for
String code2 = "";
code2 += "using System;" + lf;
code2 += "public class ExecClass { static void Exec( Action<char, char> print";
object[] invokeArgs = new object[ argValues.Count+1];
invokeArgs[0] = new Action<char, char>(DoPrint);
int iValueIndex = 1;
foreach ( var kv in argValues )
{
code2 += ",";
code2 += "int " + kv.Key;
invokeArgs[iValueIndex] = Int32.Parse(kv.Value);
iValueIndex++;
}
code2 += ") {" + lf;
code2 += code;
code2 += "} };";
if( bDebug )
{
int line = 1;
String lineNumberedCode =Regex.Replace(code2, "^(.*)$",
delegate(Match m) { return (line++).ToString("d2") + ": " + m.Value; },
RegexOptions.Multiline
);
Console.WriteLine(lineNumberedCode);
Console.WriteLine();
Console.WriteLine();
}
left[0] = Console.CursorLeft;
for( int i = 1; i < left.Length; i++ )
left[i] = left[0];
top = Console.CursorTop;
try
{
var compileResult = new CSharpCodeProvider().CompileAssemblyFromSource( new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true }, code2);
if (compileResult.Errors.HasErrors)
{
foreach (CompilerError ce in compileResult.Errors)
{
if (ce.IsWarning) continue;
Console.WriteLine("{0}({1},{2}: error {3}: {4}", ce.FileName, ce.Line, ce.Column, ce.ErrorNumber, ce.ErrorText);
}
return;
}
var method = compileResult.CompiledAssembly.GetType("ExecClass").GetMethod("Exec", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
method.Invoke(null, invokeArgs);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.SetCursorPosition(1, lastTop);
Console.WriteLine();
Console.WriteLine();
} //Main
}
Bunun gibi komut satırı argümanları: -d "1 / \ | / _ / \ | / ___ \ 2 __ | / 0n {na-1 {½} 1a {2 # 1} $}" 3
Bu çıktı olacak:
01: using System;
02: public class ExecClass { static void Exec( Action<char, char> print,int n) {
03: for ( int a = 0; a < n ; a++ )
04: {
05: for ( int b = 0; b < n-a-1 ; b++ )
06: {
07: print('1' , '~');
08: }
09: print('1' , ' ');
10: for ( int c = 0; c < a ; c++ )
11: {
12: print('2' , ' ');
13: print('1' , '#');
14: }
15: print('$' , ' ');
16: }
17: } };
/\
/_/\
/__\_\
/\ \__/\
/_/\/ /_/\
/__\_\/__\_\
/\ \__/\ \__/\
/_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\