起因
现在ACM用得多的基本上就两种语言,C++和Python3,还有部分Java,但是当年ACM必学的Pascal、新近流行的rust也有人用,只不过用户很少。
就以一道codeforce上的算法小题为样本,来对比一样用户数量、执行效率、易写程度。
题目
https://codeforces.com/contest/1997/problem/C
样本总量:20150
用户数量对比
C++20:7800
C++17:9150
C++11:1550
Python3:1050
Python2:1
Haskell:2
C:45
C#:17
Go:14
Java21:450
Java8:180
Kotlin:9
Pascal(FPC):3
Rust:30
各语言数量差异很大,很直观。基本上是C++统治的时代了。
语言代码量对比
就取各语言中代码量最少的一个
C++20
cpp
#include<bits/stdc++.h>
using namespace std;
int t,n,ans;
string st;
int main(){
cin>>t;
while(t--){
cin>>n>>st;
ans=n/2;
for(int i=0;i<n;i++)
if(st[i]=='(')
ans+=2;
cout<<ans<<endl;
}
return 0;
}
C
cpp
#include <stdio.h>
char s[200100];
int main(void){
int tt, ii;
int ans;
int n, i;
scanf("%d", &tt);
for (ii=1; ii<=tt; ii++){
scanf("%d", &n);
ans=n/2;
scanf("%s", s+1);
for (i=1; i<=n; i++){
if (s[i]=='('){
ans+=2;
}
}
printf("%d\n", ans);
}
return 0;
}
C++14
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
string st;
int t,n,ans;
cin>>t;
while(t--){
cin>>n>>st;
ans=n/2;
for(int i=0;i<n;i++)
if(st[i]=='(')
ans+=2;
cout<<ans<<endl;
}
return 0;
}
Python3
python
for _ in[0]*int(input()):print((y:=int(input()))//2+2*input().count('('))
Pascal
Delphi
Var
t,i,n,dem1:Longint;
kq:Int64;
a:Array[0..300000] of Longint;
Procedure giai;
Var i:Longint;
s:ansistring;
Begin
Readln(n);
Readln(s);
{d1:=0;d2:=0;
For i:=1 to length(s) do if i mod 2=0 then
If s[i]='(' then inc(d1) else inc(d2); Inc(d1);}
dem1:=1;
a[dem1]:=1;
kq:=0;
For i:=2 to length(s) do
If s[i]=')' then
Begin
kq:=kq+i-a[dem1];
Dec(dem1);
End
Else if s[i]='(' then
Begin
Inc(dem1);
a[dem1]:=i;
End
Else if dem1>0 then
Begin
kq:=kq+i-a[dem1];
Dec(dem1);
End
Else
Begin
Inc(dem1);
a[dem1]:=i;
End;
Writeln(kq);
End;
BEGIN
// Assign(input,'contest168c.inp');Reset(input);
// Assign(output,'contest168c.out');Rewrite(output);
Readln(t);
For i:=1 to t do giai();
END.
Rust
rust
use std::io::*;
fn main() {
let s = read_to_string(stdin()).unwrap();
let mut it = s.lines();
let mut nx = || it.next().unwrap();
let t: usize = nx().parse().unwrap();
for _ in 0..t {
let _: usize = nx().parse().unwrap();
let s = nx().chars();
let mut sum = 0;
let mut st = vec![];
for (i,ch) in s.enumerate() {
if ch == '_' {
if st.is_empty() {
st.push(i);
} else {
sum += i - st.pop().unwrap();
}
} else if ch == '(' {
st.push(i);
} else {
sum += i - st.pop().unwrap();
}
}
println!("{sum}");
}
}
Java
java
import java.util.*;
public class RanitMukherjee {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-- > 0) {
int n = sc.nextInt();
char[] arr = sc.next().toCharArray();
int count = 0;
for(int i = 1; i < n; i+=2) {
if(arr[i] == '(') count += 3;
else count++;
}
System.out.println(count);
}
sc.close();
}
}
Haskell
Haskell
import qualified Data.ByteString.Char8 as C
import Data.Maybe
constOpen :: Char
constOpen = '('
constClose :: Char
constClose = ')'
constBlank :: Char
constBlank = '_'
parseInt :: C.ByteString -> Int
parseInt x = fst (fromJust (C.readInt x))
getInts :: IO [Int]
getInts = do
line <- C.getLine
let res = map (parseInt) (C.words line)
return res
parseStr :: C.ByteString -> String
parseStr x = C.unpack x
getStrs :: IO [String]
getStrs = do
line <- C.getLine
let res = map (parseStr) (C.words line)
return res
fill :: String -> String
fill [x] = [x]
fill (x : y : rest)
| (y == constBlank && x == constOpen) = x : constClose : fill rest
| (y == constBlank && x == constClose) = x : constOpen : fill rest
| otherwise = fill (y : rest)
getBracketPairs :: [(Char, Int)] -> [Int] -> [(Int, Int)]
getBracketPairs [] _ = []
getBracketPairs ((c, i) : rest) stack
| (c == constOpen) = getBracketPairs rest (i : stack)
| otherwise = (i, head stack) : getBracketPairs rest (tail stack)
ans :: IO ()
ans = do
[n] <- getInts
[s] <- getStrs
let sFill = constOpen : fill (tail s)
let pairs = zip sFill [1 .. ]
let bracketPairs = getBracketPairs pairs []
let dists = map (\(x, y) -> x - y) bracketPairs
let res = sum dists
print res
return ()
main :: IO ()
main = do
[t] <- getInts
sequence (replicate t ans)
return ()
Kotlin
Kotlin
import java.util.LinkedList
fun main() {
repeat(readln().toInt()) {
val n = readln().toInt()
val s = readln()
var ans = 0L
val bracketPositions = LinkedList<Int>()
for (i in s.indices) {
var c = s[i]
if (c == '_') {
c = if (bracketPositions.isEmpty()) '(' else ')'
}
if (c == ')') {
ans += i - bracketPositions.pollLast()
}
else
bracketPositions.addLast(i)
}
println(ans)
}
}
C#
cs
using System.Text;
namespace EvenPositions;
class Program
{
private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024 * 10), Encoding.ASCII, false, 1024 * 10);
private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024 * 10), Encoding.ASCII, 1024 * 10);
private static void Main(string[] args)
{
int t = int.Parse(reader.ReadLine());
for (int i = 0; i < t; i++)
{
writer.WriteLine(Solve());
}
writer.Flush();
}
private static int Solve()
{
reader.ReadLine();
string s = reader.ReadLine();
int ans = 0;
for (int i = 1; i < s.Length; i += 2)
{
if (s[i] == ')') ans += 1;
else ans += 3;
}
return ans;
}
}
总结
一个语言用户数量的多少,最相关的还是难易程度,同样的代码写起来越简单肯定越受人喜欢;其次就是运行效率,尽管简单,过不了运行测试也不行;再就是用户基数,用的人多,学习资料才多,而用户基数就是前面两点确定的。