برنامه نویسی به زبان ارلنگ

ارلنگ زبان برنامه نویسی تابعی و همروند است

برنامه نویسی به زبان ارلنگ

ارلنگ زبان برنامه نویسی تابعی و همروند است

برنامه نویسی به زبان ارلنگ

در این وبلاگ مطالب مربوط به ارلنگ و الیکسیر منتشر خواهد شد

۱۵ مطلب با کلمه‌ی کلیدی «مثال هایی در ارلنگ» ثبت شده است

  • ۰
  • ۰

در این مثال دو رشته از ورودی دریافت می‌شود و سپس بررسی می‌شود که آیا آن دو آناگرام هستند یا نه. دو رشته را در حالی آناگرام می‌گویند که از کارکترهای یکسانی تشکیل شده باشند. برای نمونه note و tone آناگرام هستند. برای حل این مثال از نوع map استفاده کردم که در آن هر کارکتر یک کلید و تعداد تکرارش مقدار آن می‌باشد.

%%@author Mahdi Hosseini Moghaddam <m.hoseini.m@gmail.com>
%%@doc Exercise 24 from "Exercises for programmers" Book
%%@reference from <a href="http://erlang.blog.ir">مثال هایی در ارلنگ</a>,
%% 2018
%%@copyright 2018 by Mahdi Hosseini Moghaddam
%%@version 0.1
-module(ex24).
-export([main/0]).
-compile([debug_info]).

main() ->
	try run()
	catch
		error:_Error -> io:format(
			"Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	{P,Q} = readItems(),
	A = isAnagram(P,Q),
	if
		A ==true -> 
			io:fwrite("~s and ~s are anagram ~n", [P,Q]);
		true ->
			io:fwrite("~s and ~s are not anagram ~n", [P,Q])
	end.
%@ this function whether two strings have the same characters
isAnagram(W1,W2) ->	
	M1 = count_char(W1),
	M2 = count_char(W2),
	maps:keys(M2) =:= maps:keys(M1).
	
count_char(Str) -> count_char(Str, #{}).
%@ this function put the characters and numbers of their occurrence in a map
count_char([H|T], X) ->
	 case maps:is_key(H,X) of
        false -> count_char(T, maps:put(H,1,X));
        true  -> Count = maps:get(H,X),
                 count_char(T, maps:update(H,Count+1,X))
    end;
count_char([], X) ->
	X.
%@doc This function reads the user input the returns the result	
readItems() ->
	{ok,[P]} = io:fread(
		"Enter the First word: ","~s"),
	{ok,[Q]} = io:fread(
		"Enter the Second word: ","~s"),
	{P,Q}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

برنامه‌ای بنویسند که نام کاربری و گذارواژه را از کاربر سوال کند و سپس بررسی کند که برای آن نام کاربری، گذرواژه درستی استفاده شده است یا نه. در صورت صحت گذرواژه پیام خوش آمدگویی چاپ کند و در صورت خلاف آن پیام خطا را به کاربر نشان دهد. توجه داشته باشید که گذرواژه ورودی توسط کاربر نمایش داده نمی‌شود. نمونه‌ی خروجی برنامه باید بصورت زیر باشد:

Enter your username: Mahdi

Enter your password:

Welcome Mahdi!

 

%%@author Mahdi Hosseini Moghaddam <m.hoseini.m@gmail.com>
%%@doc Exercise 15 from "Exercises for programmers" Book
%%@reference from <a href="http://erlang.blog.ir">مثال هایی در ارلنگ</a>,
%% 2018
%%@copyright 2018 by Mahdi Hosseini Moghaddam
%%@version 0.1
-module(ex15).
-export([main/0]).

%@doc This is my main function, It handles the exceptions and runs the program
main() ->
	try run()
	catch
		error:{badkey,_} -> io:format(
			"Your account does not exist~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.
%@doc This fucntion print out the result, it first calls readData function then check_login to calculate the result
run() ->
	Account = readData(),
	Result = check_login(Account),
	if
		Result == true ->
			io:fwrite("Login Succeed! ~n");
		true ->
			io:fwrite("Login failed! ~n")
	end.
%@doc This function check the account exist it first try to retrieve the account, if the account exist it then compare the hash version of the entered password with the stored one. if the account does not exist it prompt different message 
check_login({User, Passwd}) ->
	Map = accounts(),
	Val=maps:get(User, Map),
	Val == crypto:hash(sha256,Passwd).
accounts() ->
		#{"mahdi" => crypto:hash(sha256,"123456")}.
%@doc This function reads the user input the returns the result
readData() ->
	Usr = string:strip(io:get_line("Enter your username: "),right,$\n),
	io:fwrite("Enter you password:"),
	Passwd = io:get_password(),
	{Usr, Passwd}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

در این مثال قرار است کارکردن با عبارات شرطی نظیر if تست شود هرچند در ارلنگ در بسیاری از موارد می‌توان از آن صرفنظر کرد و با خود توابع و تطابق الگو به این کارکرد رسید. برای این مثال قرار است مبلغ و اسم ایالت پرسیده شود چنانچه نام ایالت WI بود 5.5% درصد مالیات محاسبه شده و مقدار کل برگردد و در غیر اینصورت همان مبلغ اصلی برگشت داده شود. برای چاپ خروجی از if استفاده کردم اما برای محاسبه با استفاده از تطابق الگو تمایز ایجاد کردم.  در این مثال برای نخستین بار سعی در مستند سازی کد کردم که در پست مربوطه  به آن توضیح مفصل خواهم داد.

%%@author Mahdi Hosseini Moghaddam <m.hoseini.m@gmail.com>
%%@doc Exercise 14 from "Exercises for programmers" Book
%%@reference from <a href="http://erlang.blog.ir">مثال هایی در ارلنگ</a>,
%% 2016
%%@copyright 2018 by Mahdi Hosseini Moghaddam
%%@version 0.1
-module(ex14).
-export([main/0]).
-define(WITAX, 0.055).
%@doc This is my main function, It handles the exceptions and runs the program
main() ->
	try run()
	catch
		error:_Error -> io:format(
			"Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.
%@doc This fucntion print out the result, it first calls readData function then calc_Tax to calculate the result
run() ->
	{A, State} = readData(),
	{At, Taxed} = calc_Tax(A, State),
	if
		State =="WI" ->
		io:fwrite("The subtotal is $~w~n The tax is $~w~n the total is ~.2f~n"
					,[A,Taxed,At]);
		true ->
			io:fwrite("The total is $~w~n",[At])
	end.
%@doc This function calculates the tax
calc_Tax(A,"WI") -> 
	{A * (1+?WITAX),A * ?WITAX};
calc_Tax(A,_) ->
	{A,0}.
	
%@doc This function reads the user input the returns the result, it checks for invalid input like negative numbers
readData() ->
	{ok,[A]} = io:fread(
		"What is the order amount? ","~d"),
	State = string:strip(io:get_line("What's the state? "),right,$\n),
	if
		A =< 0  -> 
			throw(negativeNumber);
		true -> ok
	end,
	{A, State}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

این مثال عینا شبیه مثال قبل است با این تفاوت که فرمول محاسبه مبلغ نهایی تفاوت دارد.

A = P (1 + nr )^nt

در این مثال با توجه به اینکه تنها به دو رقم اعشار در جواب نیاز دارم از .2f استفاده کردم که در تابع io:format مشهود است. 

-module(ex13).
-export([main/0]).
-compile([debug_info]).

main() ->
	try run()
	catch
		error:_Error -> io:format(
			"Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	{P,R,T,N} = readItems(),
	A = calc_Investment({P,R,T,N}),
	io:fwrite(
		"$~w invested at ~w% for ~w years compounded ~w times per year is $~.2f",
		[P,R,T,N,A]).

calc_Investment({P,R,T,N}) -> 
	P*(math:pow(1+R/(N*100),N*T)).
	
readItems() ->
	{ok,[P]} = io:fread(
		"Enter the principal: ","~d"),
	{R,_} = string:to_float(string:strip(
			io:get_line("Enter the rate of interest: "), right, $\n)),
	{ok,[T]} = io:fread(
		"Enter the number of years: ","~d"),
	{ok,[N]} = io:fread(
		"What is the number of times the interest is compounded per year? ","~d"),
	if
		P =< 0 orelse R =< 0 orelse T =< 0 orelse N =< 0 -> 
			throw(negativeNumber);
		true -> ok
	end,
	{P,R,T,N}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

این مثال محاسبه سود است. برای مثال اگر شما 1500 دلار داشته باشید و سالانه 4.3% سود بگیرید بعد از 4 سال پول شما از طریق فرمول زیر به 1758 خواهد رسید.

A = P(1 + rt)

که در آن r همان نرخ سود و t تعداد سال است و P هم همان پول اولیه شماست. در نوشتن این کد به مشکلی برخوردم و آنهم خواندن نوع اعشاری بود که در کد نحوه آن قابل مشاهده است. نکته دیگر استفاده از دیباگر ارلنگ بود. برای این کار باید debug_info را به نحوه زیر به کد اضافه کنید. کار با دیباگر ارلنگ را در زیر کد توضیح خواهد داد.

-module(ex12).
-export([main/0]).
-compile([debug_info]).

main() ->
	try run()
	catch
		error:_Error -> io:format(
			"Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	{P,I,Y} = readItems(),
	Total = calc_Investment({P,I,Y}),
	io:fwrite(
		"After ~w years at ~w%, the investment will be worth $~w.",
		[Y,I,Total]).

calc_Investment({P,I,Y}) -> 
	P*(1+(I*Y/100)).
	
readItems() ->
	{ok,[P]} = io:fread(
		"Enter the principal: ","~d"),
	%{ok,[I]} = io:fread(
	%	"Enter the rate of interest: ","~f"),
	{I,_} = string:to_float(string:strip(
			io:get_line("Enter the rate of interest: "), right, $\n)),
	{ok,[Y]} = io:fread(
		"Enter the number of years: ","~d"),
	if
		P =< 0 orelse I =< 0 orelse Y =< 0 -> 
			throw(negativeNumber);
		true -> ok
	end,
	{P,I,Y}.

خوب همانطور که مشخص است ابتدا debug_info  را به کد اضافه می‌کنیم. کد را به صورت معمول کامپایل کرده و سپس دیباگر را اجرا می‌کنیم. دیباگر یک محیط گرافیکی دارد که باید ماژول خود را از قسمت Module انتخاب کنیم و سپس تابع اصلی را انتخاب کنیم. می‌توانیم خیلی ساده روی هر خط کد break بگذاریم و خط به خط پیش رویم. کامند ها را بترتیب زیر اجرا می‌کنیم:

163> c(ex12,debug_info).
{ok,ex12}
164> debugger:start().
{ok,<0.552.0>}
  • مهدی حسینی مقدم
  • ۰
  • ۰

در این مثال قیمت سه آیتم از کاربر از ورودی بهمراه تعداد هر کدام را دریافت می‌کنیم و قیمت نهایی را با در نظر گرفتن 5.5% مالیات محاسبه می‌کنیم که بسیار ساده است. در این مثال قسمت دریافت اطلاعات، چاپ خروجی و محاسبات را از هم جدا کردم و ضمنا تابع محابسه بصورت بازگشتی تعریف شده است.

-module(ex10).
-export([main/0]).
-define(TAX, 0.55).

main() ->
	try run()
	catch
		error:_Error -> io:format(
			"Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	L = readItems(),
	[Sub,Taxed,Total] = calc_tax(L),
	io:fwrite(
		"Subtotal: $~w~nTax: $~w~nTotal: $~w~n",
		[Sub,Taxed,Total]).

calc_tax(L) -> calc_tax(L,0).
calc_tax([],Total) ->
	[Total, Total*?TAX,(1+?TAX)*Total];
calc_tax([{P,Q}|T],Total) ->
	calc_tax(T,Total+(P*Q)).
	
readItems() ->
	{ok,[P1]} = io:fread(
		"Enter the price of item 1: ","~d"),
	{ok,[Q1]} = io:fread(
		"Enter the quantity of item 1: ","~d"),
	{ok,[P2]} = io:fread(
		"Enter the price of item 2: ","~d"),
	{ok,[Q2]} = io:fread(
		"Enter the quantity of item 2: ","~d"),
	{ok,[P3]} = io:fread(
		"Enter the price of item 3: ","~d"),
	{ok,[Q3]} = io:fread(
		"Enter the quantity of item 3: ","~d"),
	if
		P1 =< 0 orelse Q1 =< 0 orelse P2 =< 0 orelse Q2 =< 0 orelse
		P3 =< 0 orelse Q3 =< 0 -> throw(negativeNumber);
		true -> ok
	end,
	[{P1,Q1},{P2,Q2},{P3,Q3}].
  • مهدی حسینی مقدم
  • ۰
  • ۰

این مثال ساده در حقیقت سعی دارد شما را با عملگرهای div و rem آشنا کند که اولی تقسیم صحیح و دومی باقیمانده است. در این مثال شما باید برنامه‌ئی بنویسید که طول و عرض یک دیوار را دریافت کند( با در نظر گرفتن این نکته که برای رنگ کردن هر 350 فوت مربع یه گالون رنگ نیاز است و همچنین امکان خرید قسمتی از یک گالون نیست و باید یک گالون کامل بخریم) و بشما اعلام کند چه تعداد گالون نیاز دارید. برای مثال اگر مساحت دیوار 351 فوت مربع باشد شما به دو گالون رنگ نیاز دارید.

-module(ex9).
-export([main/0]).
-define(GALLON, 350).

main() ->
	try run()
	catch
		error:_Error -> io:format(
			"Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	{Length, Width} = readDimension(),
	D = calc_gallon(Length,Width),
	io:fwrite(
		"You will need to purchase ~w gallons of paint 
		to cover ~w square feet.~n",
		[D,Length*Width]).

calc_gallon(Length, Width) ->
	D = Length * Width,
	if
		D div ?GALLON == D / ?GALLON -> D div ?GALLON;
		true -> (D div ?GALLON) + 1
	end.
	
readDimension() ->
	{ok,[First]} = io:fread(
		"What is the length of the wall in feet? ","~d"),
	{ok,[Second]} = io:fread(
		"What is the width of the wall in feet? ","~d"),
	if
		First =< 0 orelse Second =< 0 -> throw(negativeNumber);
		true -> ok
	end,
	{First,Second}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

برنامه‌ای بنویسد که با دریافت تعداد نفرات یک مهمانی و همچنین تعداد پیتزای موجود و البته تعداد تکه‌های هر پیتزا محاسبه کند که بهر نفر چند تکه می‌رسد. قطعات قابل ریز شدن نیستند و بنابرین سهم هر نفر عدد صحیح خواهد بود و طبیعتا در برخی موارد تعدادی  پیتزا باقی خواهد ماند. بنابراین برنامه سهم نفر و تعداد باقی مانده را خواهد نوشت. برای مثال ورودی های زیر خروجی نوشته شده را خواهد داد:

Input:

How many people? 4

How many pizzas do you have? 5

How many slices each pizza have? 7

Output:

4 People with 5 pizzas which have 7 slices per each

Each Person will have 8 slices

there are 3 leftover

کد این برنامه بشرح زیر خواهد بود:

 

-module(ex8).
-export([main/0]).

main() ->
	try run()
	catch
		error:_Error -> io:format("Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	{Poeple, Pizzas, Slices} = readServing(),
	io:fwrite("~w People with ~w pizzas which have ~w slices per each~n",
		[Poeple,Pizzas,Slices]),
	io:fwrite("Each Person will have ~w slices~n there are ~w leftover~n",
		[(Pizzas*Slices) div Poeple, (Pizzas*Slices) rem Poeple]).

	
readServing() ->
	{ok,[Poeple]} = io:fread(
		"How many people? ","~d"),
	{ok,[Pizzas]} = io:fread(
		"How many pizzas do you have? ","~d"),
	{ok,[Slices]} = io:fread(
		"How many slices each pizza have? ","~d"),
	if
		Poeple =< 0 orelse Pizzas =< 0 orelse Slices =< 0 -> throw(negativeNumber);
		true -> ok
	end,
	{Poeple,Pizzas,Slices}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

مثال بعدی محاسبه مساحت یک مستطیل است. واحد دریافتی از کاربر فوت هست و خروجی باید مساحت به فوت مربع و متر مربع باشد. برای تبدیل فوت مربع به متر مربع باید آن را در عدد ثابت 0.09290304 ضرب کنیم. این عدد را بصورت ماکرو در ابتدای برنامه تعریف کردم. برای استفاده از ماکرو در ارلنگ نام آن را که صرفا بخاطر یک قرارداد بصورت حروف بزرگ نوشته می‌شود را با ؟ فراخوانی می‌کنیم، کد زیر برنامه مورد نظر است:

-module(ex7).
-export([main/0]).
-define(CONRATE,0.09290304).

main() ->
	try run()
	catch
		error:_Error -> io:format("Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format(
			"Please Enter only non-zero positive number~n")
	end.

run() ->
	{Length, Width} = readDimension(),
	D = calc_area(Length,Width),
	io:fwrite("You entered dimensions of ~w feet by ~w feet.~n",
		[Length,Width]),
	io:fwrite("The area is~n ~w square feet~n ~w square meters~n",
		[D, D * ?CONRATE]).

calc_area(Length, Width) ->
	Length * Width.
	
readDimension() ->
	{ok,[First]} = io:fread(
		"What is the length of the room in feet? ","~d"),
	{ok,[Second]} = io:fread(
		"What is the width of the room in feet? ","~d"),
	if
		First =< 0 orelse Second =< 0 -> throw(negativeNumber);
		true -> ok
	end,
	{First,Second}.
  • مهدی حسینی مقدم
  • ۰
  • ۰

این مثال بسیار شبیه مثال قبلی است. دو عدد از ورودی در یافت می‌شود. اولی سن شماست و دومی سنی که دوست دارید بازنشسته شوید. سپس قرار است بشما بگوید که چند سال تا بازنشستگی دارید ( که خیلی ساده با کسر کردن سن کنونی از سن مورد نظر برای بازنشستگی بدست می‌آید) و چه سالی بازنشسته خواهید شد. این قسمت کمی چالشی است زیرا شما نیاز دارید با توابع خاصی سال کنونی را از سیستم استخراج کنید. تابع مورد نظر local_time است که در ماژول سیستمی calendar موجود است.  از آنجایی که ما تنها به سال کنونی نیاز داریم باقی را نادیده می گیریم. خروجی این تابع بصورت زیر است:

{{Year, Month, Day}, {Hour, Minute, Second}}
کد برنامه به شرح زیر است: 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-module(ex6).
-export([main/0]).

main() ->
	try run()
	catch
		error:_Error -> io:format("Please Enter only Numeric type~n");
		throw:negativeNumber -> io:format("Please Enter only positive number~n");
		throw:outOfBound -> io:format("You are already retired~n")
	end.
	
run() ->
	{Cur,Retire} = readInteger(),
	{{Year,_,_},_} = calendar:local_time(),
	io:fwrite("you have ~w years before retirement~n",[Retire - Cur]),
	io:fwrite("It's ~w so you be retired in ~w ~n",[Year,Year+(Retire - Cur)]).

readInteger() ->
	{ok,[First]} = io:fread("What's you current age? ","~d"),
	{ok,[Second]} = io:fread("At what age would you like to retire? ","~d"),
	if
		First < 0 orelse Second < 0 -> throw(negativeNumber);
		First > Second -> throw(outOfBound);
		true -> ok
	end,
	{First,Second}.

خط 14 ما تنها مقدار سال را به متغیر Year انتقال می‌دهیم و باقی را دور می‌ریزیم. ضمنا سیستم برای مواقعی که سن مورد نظر برای بازنشستگی کمتر از سن کنونی شماس خطا خواهد داد. 

  • مهدی حسینی مقدم