2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

超どマイナー言語「ECLiPSe」を競プロで使ってみる

Last updated at Posted at 2024-02-08

超軽く自己紹介

こんにちは、yaakiyuです。競技プログラミングをやっていたり、discordでbotを作っていたりします。AtCoder緑でまだまだよわよわプログラマーですがよろしくお願いします!

ECLiPSeってなんじゃい?

僕がこの言語に出会ったのはAtCoder ProblemsのLanguage Ownerのランキングでのこと。自分でもランキングに乗れるような言語はないかなーと探していたときにECLiPSeという言語に出会った。2位の方が1ACだったので、なんとか1問ぐらい行けるだろ!と思って調べ始めた。

...見つからない!EclipseといえばJavaを開発するときの統合開発環境(IDE)が有名すぎて、まったくプログラミング言語のECLiPSeに出会わない。

これはAtCoder上の他の人のコードを見て学ぶしかないか...と見始めたところ、コンパイルメッセージのところに面白い文章が。

ECLiPSe Constraint Logic Programming System [kernel threads]
Kernel and basic libraries copyright Cisco Systems, Inc.
and subject to the Cisco-style Mozilla Public Licence 1.1
(see legal/cmpl.txt or http://eclipseclp.org/licence)
Source available at www.sourceforge.org/projects/eclipse-clp
GMP library copyright Free Software Foundation, see legal/lgpl.txt
For other libraries see their individual copyright notices
Version 7.1beta #13 (x86_64_linux), Sun Jan  1 18:01 2023
Main.ecl   compiled 744 bytes in 0.00 seconds

bye

「bye」って、かわいいな。というのは置いといて、僕が注目したのは途中のこの一文。

(see legal/cmpl.txt or http://eclipseclp.org/licence)

これ、後半のhttp://eclipseclp.org/licenceって、公式ホームページの一部なんじゃない!?

と思ってlicenceの部分をURLから消したらありました。

ECLiPSe Home

このサイトを見ながら基本文法とかを学びました。

1問解いてみる

まずはHello, world!を出力するだけの問題を、いろいろ調べながら解いてみた。
https://atcoder.jp/contests/APG4b/submissions/46935632

image.png
文法的には、

  • main関数?の中に書く(引数っぽい部分がないのでこれが関数なのかはわからない...)
  • write関数を使って出力(改行は自動的にはつかないので\nをつける必要あり)
  • 最後(厳密には異なる)に.を書く

みたいな感じです。やってみて「マイナー言語にしては意外と機能多くて高級言語っぽいな〜」という感想でした。

文法解説

自分がわかる範囲で文法について解説します。間違っていたらコメントなどでご指摘ください。

入出力

入力はread_string、出力はwriteで可能です。read_stringの方は引数がいくつかついていますが、(自分でもよくわからないので)暗記したほうがいいでしょう。

main : 
    read_string(user_input, " \n", "", _, S),
    write(S).

ちなみに、2つ以上の動作を並列して書く場合、各行ごとに,で区切らないとコンパイルエラーが出ます。(最後の.は無くてもエラーは出ないが、あったほうがよさそう)

コメント

%から始まる部分はコメントとしてみなされます。カンマも必要ありません。

main :-
    % ここはコメント。なにもしないぜ
    write("ここは文字列").

変数と数値計算

変数になにかを代入するときは=もしくはisを使います。
=では後に書かれたものがそのまま文字列として代入されますが、isを使うとその中身が実行されて代入されます。
数値計算を行う場合はisを使わなければ演算ができません。

main :-
    X = 5,
    write(X),  % 5
    Y = X * 2, 
    write(Y),  % X * 2
    A is X * 2,
    write(A).  % 10

さいごに

おめでたいことにいろいろ調べながら4ACし、無事Language Ownerの2位に乗ることができました。...1位の方、65ACとかすごくないですか...!?
image.png

追記:ナップサック問題を解く(!?)

いきなり高度なことができるようになりました。もちろん、公式サイトから辿っていったら例示コードがあったからなんですけど。

ECLiPSeWiki | Examples / Knapsack

%
% ECLiPSe SAMPLE CODE
%
% 0-1-Knapsack problem from
% http://rosettacode.org/wiki/Knapsack_problem
% Pack 0 or 1 item of each type, obeying knapsack weight constraint.
%
% Using ic (as a finite-domain solver) and ic_sets (set-solver)
%

:- lib(ic).
:- lib(ic_sets).
:- lib(branch_and_bound).

model(Weights, Values, Capacity, Knapsack, Weight, Value) :-
	dim(Weights, [N]),
	dim(Values,  [N]),
	intset(Knapsack, 1, N),		% Knapsack is a subset of integers 1..N
	Weight #=< Capacity,
	weight(Knapsack, Weights, Weight),
	weight(Knapsack, Values, Value).

solve(Weights, Values, Capacity, Knapsack, Weight, Value) :-
	model(Weights, Values, Capacity, Knapsack, Weight, Value),
	Cost #= -Value,		% need Cost for minimizing!
	minimize(insetdomain(Knapsack,_,heavy_first(Values),in_notin), Cost).

main :-
    	data(Names, Weights, Values, Capacity),
	solve(Weights, Values, Capacity, Knapsack, Weight, Value),
	( foreach(I,Knapsack), param(Names) do
	    arg(I, Names, Name),
	    writeln(Name)
	),
	writeln(weight=Weight;value=Value).


% data(Names, Weights, Values, Capacity)
data(
    [](map,compass,water,sandwich,glucose,tin,banana,apple,cheese,beer,
       'suntan cream',camera,'t-shirt',trousers,umbrella,'waterproof trousers',
       'waterproof overclothes','note-case',sunglasses,towel,socks,book),
    [](  9,13,153, 50,15,68,27,39,23,52,11,32,24,48,73,42,43,22, 7,18, 4,30),
    [](150,35,200,160,60,45,60,40,30,10,70,30,15,10,40,70,75,80,20,12,50,10),
    400
).

このコードを(フィーリングで)読む感じ、いくつか知らなかった文法構造とか関数がありそうです。
あと最近いろいろテストしていて気が付いたことも含めて説明します。

  • 空白やハイフンを含まない文字列は引用符が不要
  • すべての変数がデフォルトでconstになっていて、再代入ができない
  • writeln関数がある
writeln("aaa"). % 「aaa\n」を出力
  • いきなり出てきたCost #= -Value#=は何もわからないけどとりあえずCostがもとからなにか用意されたものっぽそうなのを確認
main:-
    writeln(Cost). % 「_15297」が出力された
  • ライブラリのインポートをしている(ということは標準ライブラリがある)
:- lib(ライブラリ名).

でインポート可能。

ほかになにかECLiPSeについて知っている方がいたらどうかコメント欄に情報お願いします。

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?