summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controle-2020qcm.tex271
-rwxr-xr-xmisc/randomize-test.pl179
2 files changed, 450 insertions, 0 deletions
diff --git a/controle-2020qcm.tex b/controle-2020qcm.tex
new file mode 100644
index 0000000..8d80361
--- /dev/null
+++ b/controle-2020qcm.tex
@@ -0,0 +1,271 @@
+%% This is a LaTeX document. Hey, Emacs, -*- latex -*- , get it?
+\documentclass[12pt,a4paper]{article}
+\usepackage[francais]{babel}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+%\usepackage{ucs}
+\usepackage{times}
+% A tribute to the worthy AMS:
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage{amssymb}
+\usepackage{amsthm}
+%
+\usepackage{mathrsfs}
+\usepackage{wasysym}
+\usepackage{url}
+%
+\usepackage{graphics}
+\usepackage[usenames,dvipsnames]{xcolor}
+\usepackage{tikz}
+\usetikzlibrary{arrows,automata,positioning}
+\usepackage{hyperref}
+%
+\newenvironment{qcm}{\relax}{\relax}
+\newenvironment{qvar}{\relax}{\relax}
+\newcounter{quescnt}
+\newenvironment{question}%
+{\stepcounter{quescnt}\bigskip\noindent\textbf{Question~\arabic{quescnt}.}\par\nobreak}
+{\relax}
+\newcounter{answcnt}[quescnt]
+\newcommand\answer{%
+\stepcounter{answcnt}\smallskip\textbf{(\Alph{answcnt})}~}
+\let\rightanswer=\answer
+%
+\DeclareUnicodeCharacter{00A0}{~}
+\DeclareUnicodeCharacter{03B5}{$\varepsilon$}
+%
+\DeclareMathSymbol{\tiret}{\mathord}{operators}{"7C}
+\DeclareMathSymbol{\traitdunion}{\mathord}{operators}{"2D}
+%
+\newif\ifcorrige
+\corrigefalse
+%
+%
+% NOTE: compile dot files with
+% dot2tex --figonly -f tikz --tikzedgelabels --graphstyle=automaton file.dot > file.tex
+\tikzstyle{automaton}=[>=stealth',initial text={},thick,every loop/.style={min distance=7mm,looseness=5}]
+\tikzstyle{state}=[]
+\tikzstyle{final}=[accepting by arrow]
+%
+%
+%
+\begin{document}
+\ifcorrige
+\title{INF105\\Contrôle de connaissances — Corrigé\\{\normalsize Théorie des langages}}
+\else
+\title{INF105\\Contrôle de connaissances\\{\normalsize Théorie des langages}}
+\fi
+\author{}
+\date{(date à remplir)}
+\maketitle
+
+\pretolerance=8000
+\tolerance=50000
+
+\vskip1truein\relax
+
+\noindent\textbf{Consignes.}
+
+Ce contrôle de connaissances est un QCM (questionnaire à choix
+multiples). Chaque question admet une unique réponse correcte. Les
+questions sont totalement indépendantes les unes des autres. La
+sélection des questions et l'ordre ont été tirés aléatoirement et
+n'obéissent donc à aucune logique particulière.
+
+La réponse est attendue sous forme d'une liste de numéros de question
+suivie de la réponse proposée : par exemple, « \verb=1A 2B 4D= » pour
+signifier que la réponse proposée à la question 1 est (A), la réponse
+proposée à la question 2 est (B), et la réponse proposée à la
+question 4 est (D).
+
+Une réponse incorrecte sera (deux fois) plus fortement pénalisée
+qu'une absence de réponse : il est donc préférable de ne pas répondre
+à une question que de répondre aléatoirement.
+
+\medbreak
+
+Durée : (à remplir)
+
+\vfill
+
+{\tiny\noindent
+\immediate\write18{sh ./vc > vcline.tex}
+Git: \input{vcline.tex}
+\immediate\write18{echo ' (stale)' >> vcline.tex}
+\par}
+
+\pagebreak
+
+\begin{qcm}
+
+
+%
+%
+%
+
+\begin{qvar}
+
+\begin{question}
+
+Quelle est la couleur du cheval blanc d'Henri IV ?
+
+\rightanswer
+Blanc
+
+\answer
+Noir
+
+\answer
+Bleu à pois roses
+
+\end{question}
+
+\begin{question}
+
+Quelle est la couleur du cheval noir de Charlemagne ?
+
+\rightanswer
+Noir
+
+\answer
+Blanc
+
+\answer
+Bleu à pois roses
+
+\end{question}
+
+\end{qvar}
+
+
+%
+%
+%
+
+\begin{question}
+
+Qui est enterré dans le tombeau de Grant ?
+
+\rightanswer
+Grant
+
+\answer
+Charlemagne
+
+\answer
+Obi-Wan Kenobi
+
+\end{question}
+
+
+%
+%
+%
+
+\begin{question}
+
+Combien fait $2+2$ ?
+
+\rightanswer
+$4$
+
+\answer
+$696\,729\,600$
+
+\answer
+$e^{\pi\sqrt{163}}$
+
+\end{question}
+
+
+%
+%
+%
+
+\begin{question}
+
+David Madore est-il... ?
+
+\rightanswer
+l'auteur de ces questions
+
+\answer
+un arbre
+
+\answer
+une application Android
+
+\answer
+le fils caché de la reine d'Angleterre
+
+\end{question}
+
+
+%
+%
+%
+
+\begin{question}
+
+Complétez les vers : « Ô rage ! ô désespoir ! ô vieillesse ennemie ! /
+N'ai-je donc tant vécu que pour cette... ? »
+
+\rightanswer
+infamie
+
+\answer
+alchimie
+
+\answer
+momie
+
+
+\end{question}
+
+
+%
+%
+%
+
+\begin{question}
+
+La réponse correcte à cette question est-elle... ?
+
+\rightanswer
+celle-ci
+
+\answer
+une autre que celle-ci
+
+\answer
+inexistante
+
+\answer
+toutes à la fois
+
+\end{question}
+
+
+%
+%
+%
+
+\begin{question}
+
+Un quart d'heure avant sa mort, il était encore... ?
+
+\rightanswer
+en vie
+
+\answer
+mort
+
+\end{question}
+
+
+\end{qcm}
+%
+%
+%
+\end{document}
diff --git a/misc/randomize-test.pl b/misc/randomize-test.pl
new file mode 100755
index 0000000..2db3998
--- /dev/null
+++ b/misc/randomize-test.pl
@@ -0,0 +1,179 @@
+#! /usr/local/bin/perl -w
+
+use strict;
+use warnings;
+
+use Digest::SHA qw(sha256);
+
+use Getopt::Std;
+
+my %opts;
+
+getopts("c:N:n:", \%opts);
+
+my @preamble = ();
+my @postamble = ();
+my @questions = ();
+my $nbvarid = 0;
+
+
+### READ INPUT FILE
+
+if ( 1 ) { ## Keep following variables local
+
+my $in_preamble = 1;
+my $in_postamble = 0;
+my $in_qvar = 0;
+my $curqn;
+my $listref = \@preamble;
+my $varid;
+LINELOOP:
+while ($_ = <>) {
+ if ( $_ =~ m/\\begin\{qcm\}/ ) {
+ die "wrong placement" unless $in_preamble;
+ die "bad format" unless $_ eq "\\begin\{qcm\}\n";
+ $in_preamble = 0;
+ $listref = undef;
+ next LINELOOP;
+ } elsif ( $_ =~ m/\\end\{qcm\}/ ) {
+ die "wrong placement" if $in_preamble;
+ die "bad format" unless $_ eq "\\end\{qcm\}\n";
+ $in_postamble = 0;
+ $listref = \@postamble;
+ next LINELOOP;
+ } elsif ( $_ =~ m/\\begin\{qvar\}/ ) {
+ die "wrong placement" if $in_preamble || $in_postamble || $in_qvar || defined($curqn);
+ die "bad format" unless $_ eq "\\begin\{qvar\}\n";
+ $in_qvar = 1;
+ $varid = ($nbvarid++);
+ next LINELOOP;
+ } elsif ( $_ =~ m/\\end\{qvar\}/ ) {
+ die "wrong placement" if $in_preamble || $in_postamble || (!$in_qvar) || defined($curqn);
+ die "bad format" unless $_ eq "\\end\{qvar\}\n";
+ $in_qvar = 0;
+ $varid = undef;
+ next LINELOOP;
+ } elsif ( $_ =~ m/\\begin\{question\}/ ) {
+ die "wrong placement" if $in_preamble || $in_postamble || defined($curqn);
+ die "bad format" unless $_ eq "\\begin\{question\}\n";
+ my %qn = ();
+ $varid = ($nbvarid++) unless $in_qvar;
+ $qn{varid} = $varid;
+ $qn{question} = [];
+ $qn{answers} = [];
+ push @questions, \%qn;
+ $listref = $qn{question};
+ $curqn = \%qn;
+ next LINELOOP;
+ } elsif ( $_ =~ m/\\end\{question\}/ ) {
+ die "wrong placement" if $in_preamble || $in_postamble || !defined($curqn);
+ die "bad format" unless $_ eq "\\end\{question\}\n";
+ $listref = undef;
+ $curqn = undef;
+ next LINELOOP;
+ } elsif ( $_ =~ m/\\(right)?answer/
+ && $_ !~ /\\newcommand/ && $_ !~ /\\let\\rightanswer/ ) {
+ die "wrong placement" if $in_preamble || $in_postamble || !defined($curqn);
+ die "bad format" unless $_ eq "\\answer\n" || $_ eq "\\rightanswer\n";
+ die "this is impossible" unless ref($curqn) eq "HASH" && defined $curqn->{answers};
+ die "right answer should come first" unless ($_ eq "\\rightanswer\n") == (scalar(@{$curqn->{answers}}) == 0);
+ my @ans = ();
+ push @{$curqn->{answers}}, \@ans;
+ $listref = \@ans;
+ ## no next LINELOOP here: include \answer in answer itself!
+ }
+ die "this is impossible" if $in_preamble && $in_postamble;
+ die "this is impossible" if $in_preamble && ($listref ne \@preamble);
+ die "this is impossible" if $in_postamble && ($listref ne \@postamble);
+ push @{$listref}, $_ if defined($listref);
+}
+
+}
+
+# printf STDERR "nbvarid=%d (total=%d)\n", $nbvarid, scalar(@questions);
+
+
+### RANDOMIZE
+
+my $commonseed = $opts{N} // "";
+my $seed = $opts{n} // "";
+my $nbqn = $opts{c} // int(($nbvarid+1)/2);
+
+my @questab = ();
+my @quesanstab = ();
+
+if ( 1 ) { ## Keep following variables local
+
+my @hashlist;
+
+for ( my $i=0 ; $i<scalar(@questions) ; $i++ ) {
+ push @hashlist, sha256("${commonseed}\n${seed}\nQ\n${i}\n");
+}
+my @prequestab = sort { $hashlist[$a] cmp $hashlist[$b] } (0..(scalar(@questions)-1));
+my %varid_punch;
+PREQUESLOOP:
+for ( my $k=0 ; $k<scalar(@prequestab) ; $k++ ) {
+ last if scalar(@questab) > $nbqn;
+ my $i = $prequestab[$k];
+ my $qn = $questions[$i];
+ my $varid = $qn->{varid};
+ if ( defined($varid) ) {
+ if ( defined($varid_punch{$varid}) ) {
+ next PREQUESLOOP;
+ } else {
+ $varid_punch{$varid} = $i;
+ }
+ }
+ push @questab, $i;
+}
+
+for ( my $i=0 ; $i<scalar(@questions) ; $i++ ) {
+ @hashlist = ();
+ my $r = $questions[$i]->{answers};
+ for ( my $j=0 ; $j<scalar(@$r) ; $j++ ) {
+ push @hashlist, sha256("${commonseed}\n${seed}\nQ\n${i}\nA\n${j}\n");
+ }
+ my @anstab;
+ @anstab = sort { $hashlist[$a] cmp $hashlist[$b] } (0..(scalar(@$r)-1));
+ push @quesanstab, \@anstab;
+}
+
+}
+
+
+### WRITE OUTPUT FILE
+
+my @correct;
+
+foreach my $l ( @preamble ) {
+ print $l;
+}
+
+print "\\begin\{qcm\}\n\n";
+
+for ( my $k=0 ; $k<scalar(@questab) ; $k++ ) {
+ my $i = $questab[$k];
+ my $qn = $questions[$i];
+ print "\\begin\{question\}\n";
+ foreach my $l ( @{$qn->{question}} ) {
+ print $l;
+ }
+ for ( my $kk=0 ; $kk<scalar(@{$quesanstab[$i]}) ; $kk++ ) {
+ my $j = $quesanstab[$i]->[$kk];
+ my $a = $qn->{answers}->[$j];
+ foreach my $l ( @{$a} ) {
+ print $l;
+ }
+ push @correct, sprintf("%d%s", $k+1, chr(ord("A")+$kk)) if $j==0;
+ }
+ print "\\end\{question\}\n\n";
+}
+
+print "\\end\{qcm\}\n\n";
+
+printf "\%\% === %s ===\n", join(" ", @correct);
+printf "\\ifcorrige\\bigskip\\noindent\\textbf{Corrigé.} %s\\fi\n", join(" ", @correct);
+
+foreach my $l ( @postamble ) {
+ print $l;
+}