migration
2
semester-4/ОПJа/lb-1/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Викладач: Колесников Д. О.
|
||||||
|
Оцінка: 100
|
22
semester-4/ОПJа/lb-1/task1/part1.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ROOT='src/main/java'
|
||||||
|
|
||||||
|
JAVA_FILE="ua/nure/jfn/task1/Part1.java"
|
||||||
|
CLASS_FILE="ua/nure/jfn/task1/Part1.class"
|
||||||
|
|
||||||
|
CLASS="ua.nure.jfn.task1.Part1"
|
||||||
|
|
||||||
|
if [ ! -r "$ROOT/$JAVA_FILE" ]; then
|
||||||
|
echo "File '$ROOT/$JAVA_FILE' is not found or it is not readable." 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
javac "$ROOT/$JAVA_FILE"
|
||||||
|
|
||||||
|
if [ ! -r "$ROOT/$CLASS_FILE" ]; then
|
||||||
|
echo "Can't find '$ROOT/$CLASS_FILE' after compilation." 1>&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
java -cp "$ROOT" "$CLASS"
|
58
semester-4/ОПJа/lb-1/task1/pom.xml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>ua.nure.jfn</groupId>
|
||||||
|
<artifactId>task1</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.release>17</maven.compiler.release>
|
||||||
|
<junit5.version>5.12.0</junit5.version>
|
||||||
|
<surefire.version>3.5.2</surefire.version>
|
||||||
|
<spoon.version>11.2.0</spoon.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit5.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<version>${junit5.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>fr.inria.gforge.spoon</groupId>
|
||||||
|
<artifactId>spoon-core</artifactId>
|
||||||
|
<version>${spoon.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.17</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>task1</finalName>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${surefire.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,26 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
public class Demo {
|
||||||
|
|
||||||
|
private static void printSep(int k) {
|
||||||
|
System.out.printf("%nPart%d =================%n", k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
printSep(1);
|
||||||
|
Part1.main(new String[] { "A1", "B11 22 C", "D" }); // 34 7
|
||||||
|
|
||||||
|
printSep(2);
|
||||||
|
Part2.main(new String[] { "12", "18", "24" }); // 6 72
|
||||||
|
|
||||||
|
printSep(3);
|
||||||
|
Part3.main(new String[] { "5" }); // 3 5 7 11 13
|
||||||
|
|
||||||
|
printSep(4);
|
||||||
|
Part4.main(new String[] { "360" }); // 360 = 2^3 x 3^2 x 5^1
|
||||||
|
|
||||||
|
printSep(5);
|
||||||
|
Part5.main(new String[] { "1", "5", "3", "0", "5", "2", "1" }); // 5 3 0 5 2 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
public class Part1 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int numbersSum = 0;
|
||||||
|
int digitsSum = 0;
|
||||||
|
|
||||||
|
for (String arg : args) {
|
||||||
|
int digitPlace = 0;
|
||||||
|
char[] chArray = arg.toCharArray();
|
||||||
|
for (int i = chArray.length - 1; i >= 0; i--) {
|
||||||
|
char ch = chArray[i];
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
digitsSum += ch - '0';
|
||||||
|
numbersSum += (ch - '0') * pow(10, digitPlace++);
|
||||||
|
} else {
|
||||||
|
digitPlace = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("%d %d\n", numbersSum, digitsSum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pow(int num, int power) {
|
||||||
|
int result = 1;
|
||||||
|
for (int i = 0; i < power; i++) {
|
||||||
|
result *= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
public class Part2 {
|
||||||
|
|
||||||
|
static void main(String[] args) {
|
||||||
|
int num = parseInt(args[0]);
|
||||||
|
|
||||||
|
int overallGcd = num;
|
||||||
|
int overallLcm = num;
|
||||||
|
|
||||||
|
for (int i = 1; i < args.length; i++) {
|
||||||
|
num = parseInt(args[i]);
|
||||||
|
overallGcd = gcd(overallGcd, num);
|
||||||
|
overallLcm = lcm(overallLcm, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("%d %d", overallGcd, overallLcm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pow(int num, int power) {
|
||||||
|
int result = 1;
|
||||||
|
for (int i = 0; i < power; i++) {
|
||||||
|
result *= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parseInt(String str) {
|
||||||
|
int number = 0;
|
||||||
|
int digitPlace = 0;
|
||||||
|
char[] chArray = str.toCharArray();
|
||||||
|
|
||||||
|
for (int i = chArray.length - 1; i >= 0; i--) {
|
||||||
|
char ch = chArray[i];
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
number += (ch - '0') * pow(10, digitPlace++);
|
||||||
|
} else {
|
||||||
|
digitPlace = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gcd(int a, int b) {
|
||||||
|
for (int min = a < b ? a : b; min > 1; min--)
|
||||||
|
if (a % min == 0 && b % min == 0)
|
||||||
|
return min;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcm(int a, int b) {
|
||||||
|
return (a * b) / gcd(a, b);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
public class Part3 {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (int n : getPrimeNumbers(Part2.parseInt(args[0])))
|
||||||
|
System.out.printf("%d ", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] getPrimeNumbers(int n) {
|
||||||
|
if (n == 0) return new int[0];
|
||||||
|
|
||||||
|
int[] primes = new int[n];
|
||||||
|
primes[0] = 2;
|
||||||
|
|
||||||
|
for (int i = 3, c = 1; c < n; i += 2)
|
||||||
|
if (isPrime(i))
|
||||||
|
primes[c++] = i;
|
||||||
|
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPrime(int n) {
|
||||||
|
if (n <= 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 2; i * i <= n; i++) // same as i < sqrt(n)
|
||||||
|
if (n % i == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
public class Part4 {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int num = Part2.parseInt(args[0]);
|
||||||
|
|
||||||
|
System.out.printf("%d = ", num);
|
||||||
|
|
||||||
|
int counter;
|
||||||
|
for (int prime = 2; num != 1; prime = nextPrime(prime)) {
|
||||||
|
for (counter = 0; num % prime == 0; counter++)
|
||||||
|
num /= prime;
|
||||||
|
|
||||||
|
if (counter != 0)
|
||||||
|
System.out.printf("%d^%d%s", prime, counter, num != 1 ? " x " : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int nextPrime(int x) {
|
||||||
|
for (x += 1; !Part3.isPrime(x); x += 1)
|
||||||
|
;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
public class Part5 {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int[] test = { 1, 2, 3, 2, 1, 1, 4, 3, 2, 2, 1 };
|
||||||
|
for (int item : sequence(test)) {
|
||||||
|
System.out.printf("%d ", item);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] sequence(int[] ar) {
|
||||||
|
if (ar == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int n = ar.length;
|
||||||
|
|
||||||
|
int[] seq = new int[n];
|
||||||
|
int count = 0;
|
||||||
|
boolean inSeq = false;
|
||||||
|
|
||||||
|
for (int i = 1; i < n; i++) {
|
||||||
|
int a = ar[i - 1];
|
||||||
|
int b = ar[i];
|
||||||
|
|
||||||
|
if (a > b) {
|
||||||
|
seq[count++] = a;
|
||||||
|
inSeq = true;
|
||||||
|
} else if (inSeq) {
|
||||||
|
seq[count++] = a;
|
||||||
|
inSeq = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == n - 1 && inSeq)
|
||||||
|
seq[count++] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count <= 1)
|
||||||
|
return new int[0];
|
||||||
|
|
||||||
|
int[] result = new int[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
result[i] = seq[i];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Base {
|
||||||
|
|
||||||
|
{
|
||||||
|
if (ComplianceTest.MAKE_ALL_TESTS_FAILED) {
|
||||||
|
Assertions.fail("Compliance tests have not been passed", ComplianceTest.CAUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import spoon.Launcher;
|
||||||
|
import spoon.SpoonAPI;
|
||||||
|
import spoon.reflect.declaration.CtType;
|
||||||
|
import spoon.reflect.reference.CtTypeReference;
|
||||||
|
import spoon.reflect.visitor.filter.TypeFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
@Disabled("This test is used as a trigger to fail all the other tests")
|
||||||
|
class ComplianceTest {
|
||||||
|
|
||||||
|
// Assign the following option to false to skip the compliance test
|
||||||
|
// note, during testing at the stand this option will be turned on!!!
|
||||||
|
|
||||||
|
//private static final boolean TURN_TEST_COMPLIANCE_ON = false;
|
||||||
|
private static final boolean TURN_TEST_COMPLIANCE_ON = true;
|
||||||
|
|
||||||
|
public static final boolean MAKE_ALL_TESTS_FAILED;
|
||||||
|
|
||||||
|
public static final Throwable CAUSE;
|
||||||
|
|
||||||
|
private static final Object EOL = System.lineSeparator();
|
||||||
|
|
||||||
|
static {
|
||||||
|
L: {
|
||||||
|
try {
|
||||||
|
if (TURN_TEST_COMPLIANCE_ON) {
|
||||||
|
initSpoon();
|
||||||
|
startCompianceTests();
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
MAKE_ALL_TESTS_FAILED = true;
|
||||||
|
CAUSE = ex.getCause();
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
MAKE_ALL_TESTS_FAILED = false;
|
||||||
|
CAUSE = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SpoonAPI spoon;
|
||||||
|
|
||||||
|
private static void initSpoon() {
|
||||||
|
spoon = new Launcher();
|
||||||
|
spoon.addInputResource("src/main/java/");
|
||||||
|
spoon.buildModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void startCompianceTests() throws ReflectiveOperationException {
|
||||||
|
ComplianceTest cTest = new ComplianceTest();
|
||||||
|
for (Method m : ComplianceTest.class.getDeclaredMethods()) {
|
||||||
|
if (Modifier.isPrivate(m.getModifiers())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Test[] ar = m.getAnnotationsByType(Test.class);
|
||||||
|
if (ar.length > 0 && m.getAnnotationsByType(Test.class)[0] != null) {
|
||||||
|
m.invoke(cTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void appShouldNotUseForbiddenAPI() throws IOException, URISyntaxException {
|
||||||
|
URL url = getClass().getResource("forbidden-api-regex.txt");
|
||||||
|
String regex = Files.readString(Path.of(url.toURI()));
|
||||||
|
Pattern forbiddenAPIRegex = Pattern.compile(regex.toString());
|
||||||
|
StringBuilder errorMessage = new StringBuilder();
|
||||||
|
for (CtType<?> ctType : spoon.getModel().getAllTypes()) {
|
||||||
|
List<String> forbiddenAPI = ctType.getElements(new TypeFilter<>(CtTypeReference.class))
|
||||||
|
.stream()
|
||||||
|
.distinct()
|
||||||
|
.filter(r -> forbiddenAPIRegex.matcher(r.toString()).matches())
|
||||||
|
.map(CtTypeReference::getQualifiedName)
|
||||||
|
.toList();
|
||||||
|
if (!forbiddenAPI.isEmpty()) {
|
||||||
|
errorMessage.append(EOL)
|
||||||
|
.append(ctType.getQualifiedName()).append(": ")
|
||||||
|
.append(forbiddenAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!errorMessage.isEmpty()) {
|
||||||
|
fail(() -> "Using of this API is forbidden: " + errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeAppropriateNumberOfPackagesAndClasses() throws IOException, URISyntaxException {
|
||||||
|
URL url = getClass().getResource("list-of-types.txt");
|
||||||
|
String expected = Files.readString(Path.of(url.toURI())).trim();
|
||||||
|
// '\n' character is used for clarity in error message
|
||||||
|
String actual = spoon.getModel().getAllPackages().stream()
|
||||||
|
.filter(p -> p.getTypes().size() != 0)
|
||||||
|
.map(p -> p.getTypes().stream()
|
||||||
|
.map(CtType::getQualifiedName)
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining("\n")))
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
assertEquals('\n' + expected, '\n' + actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvFileSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Part1Test extends Base {
|
||||||
|
|
||||||
|
private static final PrintStream STD_OUT = System.out;
|
||||||
|
|
||||||
|
private static final String[] EMPTY = {};
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvFileSource(delimiter = ';', resources = "part1.csv")
|
||||||
|
void test(String input, String expected) {
|
||||||
|
String[] args = input == null ? EMPTY : input.split("\\s+");
|
||||||
|
if (expected == null) {
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PrintStream ps = new PrintStream(baos);
|
||||||
|
try {
|
||||||
|
System.setOut(ps);
|
||||||
|
Part1.main(args);
|
||||||
|
} finally {
|
||||||
|
System.setOut(STD_OUT);
|
||||||
|
}
|
||||||
|
assertEquals(expected, baos.toString().trim());
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvFileSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Part2Test extends Base {
|
||||||
|
|
||||||
|
private static final PrintStream STD_OUT = System.out;
|
||||||
|
|
||||||
|
private static final String[] EMPTY = {};
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvFileSource(delimiter = ';', resources = "part2.csv")
|
||||||
|
void test(String input, String expected) {
|
||||||
|
String[] args;
|
||||||
|
expected = expected == null ? "" : expected.replaceAll("_", " ");
|
||||||
|
args = input == null ? EMPTY : input.split("\\s+");
|
||||||
|
for (int j = 0; j < args.length; ++j) {
|
||||||
|
args[j] = args[j].replace("_", " ");
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PrintStream ps = new PrintStream(baos);
|
||||||
|
try {
|
||||||
|
System.setOut(ps);
|
||||||
|
Part2.main(args);
|
||||||
|
} finally {
|
||||||
|
System.setOut(STD_OUT);
|
||||||
|
}
|
||||||
|
String actual = baos.toString();
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvFileSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Part3Test extends Base {
|
||||||
|
|
||||||
|
private static final PrintStream STD_OUT = System.out;
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvFileSource(delimiter = ';', resources = "part3.csv")
|
||||||
|
void test(String input, String expected) {
|
||||||
|
if (expected == null) {
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PrintStream ps = new PrintStream(baos);
|
||||||
|
try {
|
||||||
|
System.setOut(ps);
|
||||||
|
Part3.main(new String[] { input });
|
||||||
|
} finally {
|
||||||
|
System.setOut(STD_OUT);
|
||||||
|
}
|
||||||
|
assertEquals(expected, baos.toString().trim());
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvFileSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Part4Test extends Base {
|
||||||
|
|
||||||
|
private static final PrintStream STD_OUT = System.out;
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvFileSource(delimiter = ';', resources = "part4.csv")
|
||||||
|
void test(String input, String expected) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PrintStream ps = new PrintStream(baos);
|
||||||
|
try {
|
||||||
|
System.setOut(ps);
|
||||||
|
Part4.main(new String[] { input });
|
||||||
|
} finally {
|
||||||
|
System.setOut(STD_OUT);
|
||||||
|
}
|
||||||
|
assertEquals(expected, baos.toString().trim());
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package ua.nure.jfn.task1;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvFileSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Part5Test extends Base {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvFileSource(delimiter = ';', resources = "part5.csv")
|
||||||
|
void test(String input, String expected) {
|
||||||
|
if (expected != null) {
|
||||||
|
if ("_".equals(expected)) {
|
||||||
|
expected = "";
|
||||||
|
} else {
|
||||||
|
expected = expected.replaceAll("\\s+", " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int[] ar = null;
|
||||||
|
if (input != null) {
|
||||||
|
ar = Arrays.stream(input.split("\\s+")).mapToInt(Integer::parseInt).toArray();
|
||||||
|
}
|
||||||
|
int[] result = Part5.sequence(ar);
|
||||||
|
String actual;
|
||||||
|
if (result == null) {
|
||||||
|
actual = null;
|
||||||
|
} else {
|
||||||
|
actual = IntStream.of(result)
|
||||||
|
.mapToObj(String::valueOf)
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
|
}
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
(?x)
|
||||||
|
^
|
||||||
|
(java\.(util|math)\.\S+)
|
||||||
|
|
|
||||||
|
(java\.lang\.(Byte|Short|Integer|Long|Character|Float|Double))
|
||||||
|
$
|
@ -0,0 +1,6 @@
|
|||||||
|
ua.nure.jfn.task1.Demo
|
||||||
|
ua.nure.jfn.task1.Part1
|
||||||
|
ua.nure.jfn.task1.Part2
|
||||||
|
ua.nure.jfn.task1.Part3
|
||||||
|
ua.nure.jfn.task1.Part4
|
||||||
|
ua.nure.jfn.task1.Part5
|
@ -0,0 +1,35 @@
|
|||||||
|
P4 R8 40 1 ; 53 17
|
||||||
|
x6vp 45 3 ; 54 18
|
||||||
|
5 wQ8M 9 16 ; 38 29
|
||||||
|
77ksvZg ; 77 14
|
||||||
|
z5189185 ; 5189185 37
|
||||||
|
10X H21b ; 31 4
|
||||||
|
9w6q4U4 P0b ; 23 23
|
||||||
|
43 cy01 ; 44 8
|
||||||
|
Z Q8 C d 5r7n53 ; 73 28
|
||||||
|
428 C1D ; 429 15
|
||||||
|
N 6k81 97 A 204 ; 388 37
|
||||||
|
98aPwh m 3146S13k ; 3257 35
|
||||||
|
3 Ngf ; 3 3
|
||||||
|
W2 9U9pPy ; 20 20
|
||||||
|
761 5u ; 766 19
|
||||||
|
2b Z ; 2 2
|
||||||
|
4r1662 bEfN5Z9BV93 ; 1773 45
|
||||||
|
56 q 48 ; 104 23
|
||||||
|
ph 5 ; 5 5
|
||||||
|
5p 53A81t r ; 139 22
|
||||||
|
5eg E ; 5 5
|
||||||
|
054t716 ; 770 23
|
||||||
|
23yh 0X83 6RT3 x0YV ; 115 25
|
||||||
|
2R0 7m1 17Kz5 qX7 ; 39 30
|
||||||
|
M6 YA6 7 0419f2 ; 440 35
|
||||||
|
xU68M D rq 81 0 42 ; 191 29
|
||||||
|
zSZR2r6M ; 8 8
|
||||||
|
4M2 epBT3 A6 2832 ; 2847 30
|
||||||
|
z38G0 H 565a ; 603 27
|
||||||
|
s 1V 4S 6M z8 ; 19 19
|
||||||
|
7AG 70 3 ; 80 17
|
||||||
|
0 u34 1rcvN 1 2 ; 38 11
|
||||||
|
5 rC86E2H753m4 ; 850 40
|
||||||
|
56 825R ; 881 26
|
||||||
|
FzV 1 2 H ; 3 3
|
|
@ -0,0 +1,35 @@
|
|||||||
|
18 9 ; 9 18
|
||||||
|
1 1 14 ; 1 14
|
||||||
|
12 6 ; 6 12
|
||||||
|
12 20 ; 4 60
|
||||||
|
10 16 ; 2 80
|
||||||
|
1 1 25 5 ; 1 25
|
||||||
|
12 24 ; 12 24
|
||||||
|
14 ; 14 14
|
||||||
|
11 ; 11 11
|
||||||
|
21 28 ; 7 84
|
||||||
|
21 14 ; 7 42
|
||||||
|
24 16 ; 8 48
|
||||||
|
12 30 6 ; 6 60
|
||||||
|
10 15 ; 5 30
|
||||||
|
27 9 ; 9 27
|
||||||
|
16 ; 16 16
|
||||||
|
16 8 ; 8 16
|
||||||
|
12 ; 12 12
|
||||||
|
16 24 ; 8 48
|
||||||
|
12 8 4 ; 4 24
|
||||||
|
12 16 ; 4 48
|
||||||
|
10 30 5 25 ; 5 150
|
||||||
|
14 21 ; 7 42
|
||||||
|
13 26 ; 13 26
|
||||||
|
12 3 15 6 ; 3 60
|
||||||
|
9 18 ; 9 18
|
||||||
|
1 1 11 ; 1 11
|
||||||
|
10 5 15 ; 5 30
|
||||||
|
10 16 4 6 ; 2 240
|
||||||
|
10 20 5 ; 5 20
|
||||||
|
8 16 8 ; 8 16
|
||||||
|
20 10 ; 10 20
|
||||||
|
13 ; 13 13
|
||||||
|
8 ; 8 8
|
||||||
|
18 9 27 ; 9 54
|
|
@ -0,0 +1,20 @@
|
|||||||
|
8 ; 2 3 5 7 11 13 17 19
|
||||||
|
17 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59
|
||||||
|
33 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137
|
||||||
|
16 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53
|
||||||
|
2 ; 2 3
|
||||||
|
24 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89
|
||||||
|
26 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101
|
||||||
|
7 ; 2 3 5 7 11 13 17
|
||||||
|
22 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79
|
||||||
|
15 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
|
||||||
|
14 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43
|
||||||
|
28 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107
|
||||||
|
13 ; 2 3 5 7 11 13 17 19 23 29 31 37 41
|
||||||
|
10 ; 2 3 5 7 11 13 17 19 23 29
|
||||||
|
19 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67
|
||||||
|
38 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163
|
||||||
|
30 ; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113
|
||||||
|
6 ; 2 3 5 7 11 13
|
||||||
|
12 ; 2 3 5 7 11 13 17 19 23 29 31 37
|
||||||
|
1 ; 2
|
|
@ -0,0 +1,28 @@
|
|||||||
|
111 ; 111 = 3^1 x 37^1
|
||||||
|
313 ; 313 = 313^1
|
||||||
|
658 ; 658 = 2^1 x 7^1 x 47^1
|
||||||
|
5 ; 5 = 5^1
|
||||||
|
943 ; 943 = 23^1 x 41^1
|
||||||
|
550 ; 550 = 2^1 x 5^2 x 11^1
|
||||||
|
596 ; 596 = 2^2 x 149^1
|
||||||
|
439 ; 439 = 439^1
|
||||||
|
523 ; 523 = 523^1
|
||||||
|
93 ; 93 = 3^1 x 31^1
|
||||||
|
550 ; 550 = 2^1 x 5^2 x 11^1
|
||||||
|
596 ; 596 = 2^2 x 149^1
|
||||||
|
363 ; 363 = 3^1 x 11^2
|
||||||
|
852 ; 852 = 2^2 x 3^1 x 71^1
|
||||||
|
996 ; 996 = 2^2 x 3^1 x 83^1
|
||||||
|
708 ; 708 = 2^2 x 3^1 x 59^1
|
||||||
|
369 ; 369 = 3^2 x 41^1
|
||||||
|
747 ; 747 = 3^2 x 83^1
|
||||||
|
735 ; 735 = 3^1 x 5^1 x 7^2
|
||||||
|
360 ; 360 = 2^3 x 3^2 x 5^1
|
||||||
|
783 ; 783 = 3^3 x 29^1
|
||||||
|
648 ; 648 = 2^3 x 3^4
|
||||||
|
360 ; 360 = 2^3 x 3^2 x 5^1
|
||||||
|
594 ; 594 = 2^1 x 3^3 x 11^1
|
||||||
|
500 ; 500 = 2^2 x 5^3
|
||||||
|
540 ; 540 = 2^2 x 3^3 x 5^1
|
||||||
|
904 ; 904 = 2^3 x 113^1
|
||||||
|
936 ; 936 = 2^3 x 3^2 x 13^1
|
|
@ -0,0 +1,24 @@
|
|||||||
|
1 2 3 2 1 1 4 ; 3 2 1
|
||||||
|
;
|
||||||
|
1 2 3 2 1 1 4 3 2 2 1 ; 3 2 1 4 3 2 2 1
|
||||||
|
1 2 3 4 5 ; _
|
||||||
|
1 2 3 4 5 4 ; 5 4
|
||||||
|
1 2 1 4 1 4 1 ; 2 1 4 1 4 1
|
||||||
|
5 2 1 4 1 4 5 ; 5 2 1 4 1
|
||||||
|
3 2 1 3 2 1 3 2 1 ; 3 2 1 3 2 1 3 2 1
|
||||||
|
1 2 6 2 6 4 7 8 7 8 8 1 6 8 5 8 5 2 ; 6 2 6 4 8 7 8 1 8 5 8 5 2
|
||||||
|
6 4 5 8 2 4 8 2 2 5 ; 6 4 8 2 8 2
|
||||||
|
1 1 1 7 4 7 8 7 3 7 7 4 5 8 8 3 ; 7 4 8 7 3 7 4 8 3
|
||||||
|
4 1 6 2 8 6 2 5 ; 4 1 6 2 8 6 2
|
||||||
|
5 1 6 5 4 5 1 2 2 5 5 8 ; 5 1 6 5 4 5 1
|
||||||
|
1 2 1 6 2 8 ; 2 1 6 2
|
||||||
|
6 1 7 1 2 5 4 4 4 7 7 3 6 6 8 ; 6 1 7 1 5 4 7 3
|
||||||
|
8 6 5 5 8 8 7 3 4 3 5 3 5 ; 8 6 5 8 7 3 4 3 5 3
|
||||||
|
2 7 2 2 3 2 8 2 6 ; 7 2 3 2 8 2
|
||||||
|
1 1 8 8 6 8 1 4 4 7 1 7 1 ; 8 6 8 1 7 1 7 1
|
||||||
|
4 2 4 1 7 6 3 7 1 2 1 1 4 2 3 ; 4 2 4 1 7 6 3 7 1 2 1 4 2
|
||||||
|
8 2 2 8 1 3 8 3 3 5 4 ; 8 2 8 1 8 3 5 4
|
||||||
|
1 6 4 5 7 6 7 3 3 8 4 4 5 1 8 3 8 7 ; 6 4 7 6 7 3 8 4 5 1 8 3 8 7
|
||||||
|
6 6 8 7 1 6 6 2 6 6 ; 8 7 1 6 2
|
||||||
|
5 6 2 3 7 3 2 4 4 2 ; 6 2 7 3 2 4 2
|
||||||
|
5 2 4 8 7 5 2 2 5 7 1 ; 5 2 8 7 5 2 7 1
|
|
BIN
semester-4/ОПJа/lb-1/tasks.pdf
Normal file
2
semester-4/ОПJа/lb-2/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Викладач: Колесников Д. О.
|
||||||
|
Оцінка: 98
|
58
semester-4/ОПJа/lb-2/task2/pom.xml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>ua.nure.jfn</groupId>
|
||||||
|
<artifactId>task2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.release>17</maven.compiler.release>
|
||||||
|
<junit5.version>5.12.0</junit5.version>
|
||||||
|
<surefire.version>3.5.2</surefire.version>
|
||||||
|
<spoon.version>11.2.0</spoon.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit5.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<version>${junit5.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>fr.inria.gforge.spoon</groupId>
|
||||||
|
<artifactId>spoon-core</artifactId>
|
||||||
|
<version>${spoon.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.17</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>task2</finalName>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${surefire.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,19 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
public interface Array<T> extends Container<T> {
|
||||||
|
|
||||||
|
// Returns the element at the specified position.
|
||||||
|
T get(int index);
|
||||||
|
|
||||||
|
// Returns the index of the first occurrence of the specified element,
|
||||||
|
// or -1 if this array does not contain the element.
|
||||||
|
// (use 'equals' method to check an occurrence)
|
||||||
|
int indexOf(T element);
|
||||||
|
|
||||||
|
// Removes the element at the specified position.
|
||||||
|
void remove(int index);
|
||||||
|
|
||||||
|
// Sets the element at the specified position.
|
||||||
|
void set(int index, T element);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class ArrayImpl<T> implements Array<T> {
|
||||||
|
|
||||||
|
private Object[] elements;
|
||||||
|
private int size = 0;
|
||||||
|
|
||||||
|
public ArrayImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayImpl(Container<T> container) {
|
||||||
|
this.elements = new Object[container.size() + 1];
|
||||||
|
|
||||||
|
for (T element : container)
|
||||||
|
this.add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(T element) {
|
||||||
|
if (elements == null) {
|
||||||
|
elements = new Object[255];
|
||||||
|
} else if (size == elements.length) {
|
||||||
|
Object[] newElements = new Object[elements.length * 2];
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
newElements[i] = elements[i];
|
||||||
|
|
||||||
|
elements = newElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
elements[size++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
elements[i] = null;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T get(int index) {
|
||||||
|
if (index >= size || index < 0)
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
|
||||||
|
return (T) elements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int indexOf(T element) {
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (element == null) {
|
||||||
|
if (elements[i] == null)
|
||||||
|
return i;
|
||||||
|
} else if (elements[i] != null && elements[i].equals(element))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(int index) {
|
||||||
|
if (index >= size || index < 0)
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
|
||||||
|
for (index += 1; index < size; index++)
|
||||||
|
elements[index - 1] = elements[index];
|
||||||
|
|
||||||
|
size--;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int index, T element) {
|
||||||
|
if (index >= size || index < 0)
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
|
||||||
|
elements[index] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (elements == null)
|
||||||
|
return "[]";
|
||||||
|
|
||||||
|
String repr = "[";
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (elements[i] == null)
|
||||||
|
repr += "null";
|
||||||
|
else
|
||||||
|
repr += elements[i].toString();
|
||||||
|
|
||||||
|
if (i != size - 1)
|
||||||
|
repr += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
repr += "]";
|
||||||
|
|
||||||
|
return repr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return new IteratorImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorImpl implements Iterator<T> {
|
||||||
|
int currentIndex = 0;
|
||||||
|
int lastReturnedIndex = -1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return currentIndex < size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (!hasNext())
|
||||||
|
throw new java.util.NoSuchElementException();
|
||||||
|
|
||||||
|
lastReturnedIndex = currentIndex;
|
||||||
|
return (T) elements[currentIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
if (lastReturnedIndex == -1)
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"next() has not been called, or remove() has already been called after the last next()");
|
||||||
|
|
||||||
|
ArrayImpl.this.remove(lastReturnedIndex);
|
||||||
|
currentIndex = lastReturnedIndex;
|
||||||
|
lastReturnedIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<T> stream() {
|
||||||
|
return new StreamImpl<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Array<Integer> intArray = new ArrayImpl<>();
|
||||||
|
|
||||||
|
intArray.add(10);
|
||||||
|
intArray.add(20);
|
||||||
|
intArray.add(30);
|
||||||
|
intArray.add(40);
|
||||||
|
intArray.add(20);
|
||||||
|
|
||||||
|
System.out.println("Testing get method:");
|
||||||
|
System.out.println("Element at index 0: " + intArray.get(0));
|
||||||
|
System.out.println("Element at index 2: " + intArray.get(2));
|
||||||
|
|
||||||
|
System.out.println("\nTesting indexOf method:");
|
||||||
|
System.out.println("Index of element 20: " + intArray.indexOf(20));
|
||||||
|
System.out.println("Index of element 50: " + intArray.indexOf(50));
|
||||||
|
|
||||||
|
System.out.println("\nTesting set method:");
|
||||||
|
System.out.println("Before setting: " + intArray);
|
||||||
|
intArray.set(1, 25);
|
||||||
|
System.out.println("After setting index 1 to 25: " + intArray);
|
||||||
|
|
||||||
|
System.out.println("\nTesting remove method:");
|
||||||
|
System.out.println("Before removing: " + intArray);
|
||||||
|
intArray.remove(2);
|
||||||
|
System.out.println("After removing element at index 2: " + intArray);
|
||||||
|
|
||||||
|
System.out.println("\nTesting Container interface methods:");
|
||||||
|
System.out.println("Size of array: " + intArray.size());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public interface Container<T> extends Iterable<T> {
|
||||||
|
|
||||||
|
// Appends the specified element to the end.
|
||||||
|
void add(T element);
|
||||||
|
|
||||||
|
// Removes all of the elements.
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Returns the number of elements.
|
||||||
|
int size();
|
||||||
|
|
||||||
|
// Returns a string representation of this container.
|
||||||
|
// See JUnit tests for details.
|
||||||
|
String toString();
|
||||||
|
|
||||||
|
// Returns an iterator over elements.
|
||||||
|
// Iterator must implement the remove method.
|
||||||
|
Iterator<T> iterator();
|
||||||
|
|
||||||
|
// Returns a stream over elements.
|
||||||
|
Stream<T> stream();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
public class Demo {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
public interface List<T> extends Container<T> {
|
||||||
|
|
||||||
|
// Inserts the specified element at the beginning.
|
||||||
|
void addFirst(T element);
|
||||||
|
|
||||||
|
// Removes the first element.
|
||||||
|
void removeFirst();
|
||||||
|
|
||||||
|
// Removes the last element.
|
||||||
|
void removeLast();
|
||||||
|
|
||||||
|
// Returns the first element.
|
||||||
|
T getFirst();
|
||||||
|
|
||||||
|
// Returns the last element.
|
||||||
|
T getLast();
|
||||||
|
|
||||||
|
// Returns the first occurrence of the specified element.
|
||||||
|
// Returns null if no such element.
|
||||||
|
// (use 'equals' method to check an occurrence)
|
||||||
|
T search(T element);
|
||||||
|
|
||||||
|
// Removes the first occurrence of the specified element.
|
||||||
|
// Returns true if this list contained the specified element.
|
||||||
|
// (use 'equals' method to check an occurrence)
|
||||||
|
boolean remove(T element);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,300 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class ListImpl<T> implements List<T> {
|
||||||
|
|
||||||
|
private Node<T> head;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
private static class Node<T> {
|
||||||
|
Object data;
|
||||||
|
Node<T> next;
|
||||||
|
|
||||||
|
Node(T data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node(T data, Node<T> next) {
|
||||||
|
this.data = data;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLast() {
|
||||||
|
return next == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(T element) {
|
||||||
|
if (next == null) {
|
||||||
|
next = new Node<>(element);
|
||||||
|
} else {
|
||||||
|
next.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeLast() {
|
||||||
|
if (next.isLast())
|
||||||
|
next = null;
|
||||||
|
else
|
||||||
|
next.removeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T getLast() {
|
||||||
|
if (next.isLast())
|
||||||
|
return (T) next.data;
|
||||||
|
|
||||||
|
return (T) next.getLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T search(T element) {
|
||||||
|
if (next == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (next.data != null && next.data.equals(element))
|
||||||
|
return (T) next.data;
|
||||||
|
|
||||||
|
return (T) next.search(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(T element) {
|
||||||
|
if (next == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (next.data == element || next.data.equals(element)) {
|
||||||
|
next = next.next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next.remove(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeNode(Node<T> element) {
|
||||||
|
if (next == element) {
|
||||||
|
next = next.next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next == null) {
|
||||||
|
return next.removeNode(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(T element) {
|
||||||
|
if (head == null)
|
||||||
|
head = new Node<>(element);
|
||||||
|
else
|
||||||
|
head.add(element);
|
||||||
|
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
head = null;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addFirst(T element) {
|
||||||
|
head = new Node<>(element, head);
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeFirst() {
|
||||||
|
if (head == null)
|
||||||
|
throw new java.util.NoSuchElementException();
|
||||||
|
|
||||||
|
head = head.next;
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLast() {
|
||||||
|
if (head == null)
|
||||||
|
throw new java.util.NoSuchElementException();
|
||||||
|
|
||||||
|
if (head.isLast())
|
||||||
|
head = null;
|
||||||
|
else
|
||||||
|
head.removeLast();
|
||||||
|
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T getFirst() {
|
||||||
|
if (head == null)
|
||||||
|
throw new java.util.NoSuchElementException();
|
||||||
|
|
||||||
|
return (T) head.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T getLast() {
|
||||||
|
if (head == null)
|
||||||
|
throw new java.util.NoSuchElementException();
|
||||||
|
|
||||||
|
if (head.isLast())
|
||||||
|
return (T) head.data;
|
||||||
|
else
|
||||||
|
return (T) head.getLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T search(T element) {
|
||||||
|
if (head == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (head.data != null && head.data.equals(element))
|
||||||
|
return (T) head.data;
|
||||||
|
else if (head.next != null)
|
||||||
|
return (T) head.search(element);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(T element) {
|
||||||
|
if (head == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (head.data == element || head.data.equals(element)) {
|
||||||
|
head = head.next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head.next != null) {
|
||||||
|
return head.remove(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String result = "[";
|
||||||
|
Node<T> current = head;
|
||||||
|
|
||||||
|
while (current != null) {
|
||||||
|
result += current.data != null ? current.data.toString() : "null";
|
||||||
|
|
||||||
|
if (current.next != null)
|
||||||
|
result += ", ";
|
||||||
|
|
||||||
|
current = current.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "]";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return new IteratorImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorImpl implements Iterator<T> {
|
||||||
|
|
||||||
|
Node<T> curr = head;
|
||||||
|
Node<T> prev = null;
|
||||||
|
boolean nextCalled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return curr != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (!hasNext())
|
||||||
|
throw new java.util.NoSuchElementException();
|
||||||
|
|
||||||
|
prev = curr;
|
||||||
|
curr = curr.next;
|
||||||
|
nextCalled = true;
|
||||||
|
return (T) prev.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
if (!nextCalled)
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"next() has not been called, or remove() has already been called after the last next()");
|
||||||
|
|
||||||
|
if (head == prev)
|
||||||
|
head = head.next;
|
||||||
|
else
|
||||||
|
head.removeNode(prev);
|
||||||
|
|
||||||
|
prev = null;
|
||||||
|
nextCalled = false;
|
||||||
|
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<T> stream() {
|
||||||
|
return new StreamImpl<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Integer> intList = new ListImpl<>();
|
||||||
|
|
||||||
|
System.out.println("Testing add method (from Container):");
|
||||||
|
intList.add(30);
|
||||||
|
intList.add(40);
|
||||||
|
intList.add(50);
|
||||||
|
System.out.println("List after adding elements: " + intList);
|
||||||
|
|
||||||
|
System.out.println("\nTesting addFirst method:");
|
||||||
|
intList.addFirst(20);
|
||||||
|
intList.addFirst(10);
|
||||||
|
System.out.println("List after adding elements at the beginning: " + intList);
|
||||||
|
|
||||||
|
System.out.println("\nTesting getFirst and getLast methods:");
|
||||||
|
System.out.println("First element: " + intList.getFirst());
|
||||||
|
System.out.println("Last element: " + intList.getLast());
|
||||||
|
|
||||||
|
System.out.println("\nTesting search method:");
|
||||||
|
System.out.println("Search for 30: " + intList.search(30));
|
||||||
|
System.out.println("Search for 60: " + intList.search(60));
|
||||||
|
|
||||||
|
System.out.println("\nTesting remove method (by element):");
|
||||||
|
System.out.println("Before removing 30: " + intList);
|
||||||
|
boolean removed = intList.remove(30);
|
||||||
|
System.out.println("Element 30 removed: " + removed);
|
||||||
|
System.out.println("After removing 30: " + intList);
|
||||||
|
|
||||||
|
removed = intList.remove(100);
|
||||||
|
System.out.println("Element 100 removed: " + removed);
|
||||||
|
|
||||||
|
System.out.println("\nTesting removeFirst method:");
|
||||||
|
System.out.println("Before removeFirst: " + intList);
|
||||||
|
intList.removeFirst();
|
||||||
|
System.out.println("After removeFirst: " + intList);
|
||||||
|
|
||||||
|
System.out.println("\nTesting removeLast method:");
|
||||||
|
System.out.println("Before removeLast: " + intList);
|
||||||
|
intList.removeLast();
|
||||||
|
System.out.println("After removeLast: " + intList);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
// A sequence of elements.
|
||||||
|
public interface Stream<T> {
|
||||||
|
|
||||||
|
// Represents a function that accepts one argument and produces a result.
|
||||||
|
// X - the type of the input to the function;
|
||||||
|
// Y - the type of the result of the function.
|
||||||
|
interface Function<X, Y> {
|
||||||
|
Y apply(X x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Represents an operation that accepts a single input argument
|
||||||
|
// and returns no result.
|
||||||
|
// X - the type of the input to the operation.
|
||||||
|
interface Action<X> {
|
||||||
|
void perform(X x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intermediate operations
|
||||||
|
|
||||||
|
// Returns a stream consisting of the elements of this stream that match
|
||||||
|
// the given predicate.
|
||||||
|
Stream<T> filter(Function<? super T, Boolean> predicate);
|
||||||
|
|
||||||
|
// Returns a stream consisting of the results of applying the given function
|
||||||
|
// to the elements of this stream.
|
||||||
|
<R> Stream<R> map(Function<? super T, ? extends R> function);
|
||||||
|
|
||||||
|
// terminal operations
|
||||||
|
|
||||||
|
// Returns the count of elements in this stream.
|
||||||
|
int count();
|
||||||
|
|
||||||
|
// Performs an action for each element of this stream.
|
||||||
|
void forEach(Action<? super T> action);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
public class StreamImpl<T> implements Stream<T> {
|
||||||
|
private Container<?> source;
|
||||||
|
private Array<Operation> operations;
|
||||||
|
|
||||||
|
private interface Operation {
|
||||||
|
Container<?> apply(Container<?> input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FilterOperation<T> implements Operation {
|
||||||
|
private Function<? super T, Boolean> predicate;
|
||||||
|
|
||||||
|
public FilterOperation(Function<? super T, Boolean> predicate) {
|
||||||
|
this.predicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Container<?> apply(Container<?> input) {
|
||||||
|
Array<T> newContainer = new ArrayImpl<T>();
|
||||||
|
|
||||||
|
for (Object element : input) {
|
||||||
|
if (predicate.apply((T) element))
|
||||||
|
newContainer.add((T) element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MapOperation<T, R> implements Operation {
|
||||||
|
private Function<? super T, ? extends R> function;
|
||||||
|
|
||||||
|
public MapOperation(Function<? super T, ? extends R> function) {
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Container<?> apply(Container<?> input) {
|
||||||
|
Array<R> newContainer = new ArrayImpl<R>();
|
||||||
|
|
||||||
|
for (Object element : input) {
|
||||||
|
newContainer.add(function.apply((T) element));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamImpl(Container<? extends T> container) {
|
||||||
|
this.source = container;
|
||||||
|
this.operations = new ArrayImpl<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private StreamImpl(Container<?> source, Array<Operation> operations) {
|
||||||
|
this.source = source;
|
||||||
|
this.operations = operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<T> filter(Function<? super T, Boolean> predicate) {
|
||||||
|
Array<Operation> newOperations = new ArrayImpl<>(this.operations);
|
||||||
|
newOperations.add(new FilterOperation<>(predicate));
|
||||||
|
return new StreamImpl<T>(source, newOperations);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> Stream<R> map(Function<? super T, ? extends R> function) {
|
||||||
|
Array<Operation> newOperations = new ArrayImpl<>(this.operations);
|
||||||
|
newOperations.add(new MapOperation<>(function));
|
||||||
|
return new StreamImpl<R>(source, newOperations);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int count() {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (Operation operation : operations) {
|
||||||
|
source = operation.apply(source);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void forEach(Action<? super T> action) {
|
||||||
|
for (Operation operation : operations) {
|
||||||
|
source = operation.apply(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Object element : source) {
|
||||||
|
action.perform((T) element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,262 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class ArrayImplIntegerTest extends Base {
|
||||||
|
|
||||||
|
private Array<Integer> array = new ArrayImpl<>();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Container methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[1, 2, 3]",
|
||||||
|
"1 ;[1]",
|
||||||
|
"null 2 null 4 ;[null, 2, null, 4]"
|
||||||
|
})
|
||||||
|
void testAdd(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3",
|
||||||
|
"1 2",
|
||||||
|
"null null"
|
||||||
|
})
|
||||||
|
void testClear(String input) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
array.clear();
|
||||||
|
assertEquals("[]", array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testClearEmpty() {
|
||||||
|
array.clear();
|
||||||
|
assertEquals("[]", array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 null ;4",
|
||||||
|
})
|
||||||
|
void testSize(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
int expected = Integer.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, array.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Array methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;2 ;3",
|
||||||
|
"1 2 3 ;1 ;2",
|
||||||
|
"1 2 3 ;0 ;1",
|
||||||
|
"null null ;0 ;null",
|
||||||
|
"null null ;1 ;null",
|
||||||
|
})
|
||||||
|
void testGet(String input, String indexStr, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
int index = Integer.parseInt(indexStr);
|
||||||
|
Integer expected = Utils.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, array.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 2 ;2 ;1",
|
||||||
|
"1 1 1 ;1 ;0",
|
||||||
|
"1 2 3 ;3 ;2",
|
||||||
|
"null null ;null ;0",
|
||||||
|
"1 null ;null ;1",
|
||||||
|
})
|
||||||
|
void testIndexOf(String input, String xStr, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
Integer x = Utils.parseInt(xStr);
|
||||||
|
int expected = Integer.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, array.indexOf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;0 ;[2, 3]",
|
||||||
|
"1 2 3 ;1 ;[1, 3]",
|
||||||
|
"1 2 3 ;2 ;[1, 2]",
|
||||||
|
"null 2 null ;0 ;[2, null]",
|
||||||
|
"1 null ;1 ;[1]",
|
||||||
|
})
|
||||||
|
void testRemove(String input, String indexStr, String expected) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
int index = Utils.parseInt(indexStr);
|
||||||
|
array.remove(index);
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;0 ;7 ;[7, 2, 3]",
|
||||||
|
"1 2 3 ;1 ;8 ;[1, 8, 3]",
|
||||||
|
"1 2 3 ;2 ;null ;[1, 2, null]",
|
||||||
|
"null 2 null ;2 ;null ;[null, 2, null]",
|
||||||
|
"null 2 null ;1 ;null ;[null, null, null]",
|
||||||
|
})
|
||||||
|
void testSet(String input, String indexStr, String xStr, String expected) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
int index = Integer.parseInt(indexStr);
|
||||||
|
Integer x = Utils.parseInt(xStr);
|
||||||
|
array.set(index, x);
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Iterator methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;2",
|
||||||
|
"null 3 ;3",
|
||||||
|
"1 null 3 ;null",
|
||||||
|
"null null ;null"
|
||||||
|
})
|
||||||
|
void testIteratorNext(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
Iterator<Integer> it = array.iterator();
|
||||||
|
Integer expected = Utils.parseInt(expectedStr);
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;true",
|
||||||
|
"null 3 ;false",
|
||||||
|
"1 null ;false"
|
||||||
|
})
|
||||||
|
void testIteratorHasNext(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
Boolean expected = Utils.parseBoolean(expectedStr);
|
||||||
|
Iterator<Integer> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[3]",
|
||||||
|
"null null null ;[null]",
|
||||||
|
"null null ;[]",
|
||||||
|
})
|
||||||
|
void testIteratorRemove(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
Iterator<Integer> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1",
|
||||||
|
"1 2" ,
|
||||||
|
"null null null",
|
||||||
|
})
|
||||||
|
void testIteratorRemoveShouldThrowException(String input) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
Iterator<Integer> it1 = array.iterator();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it1.remove());
|
||||||
|
Iterator<Integer> it2 = array.iterator();
|
||||||
|
it2.next();
|
||||||
|
it2.remove();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it2.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2",
|
||||||
|
"null null",
|
||||||
|
})
|
||||||
|
void testIteratorNextShouldThrowsException(String input) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
Iterator<Integer> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertThrows(NoSuchElementException.class, () -> it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;12",
|
||||||
|
"1 null 3 ;1null3",
|
||||||
|
})
|
||||||
|
void testIteratorForEach(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Integer x : array) {
|
||||||
|
sb.append(x);
|
||||||
|
}
|
||||||
|
String actual = sb.toString();
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Stream methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 4 ;24",
|
||||||
|
"11 22 33 444 ;22444",
|
||||||
|
})
|
||||||
|
void testStreamFilter(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(array, input);
|
||||||
|
if (expected == null) {
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
array.stream()
|
||||||
|
.filter(x -> x % 2 == 0)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,314 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class ArrayImplStringTest extends Base {
|
||||||
|
|
||||||
|
private Array<String> array = new ArrayImpl<>();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Container methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[1, 2, 3]",
|
||||||
|
"1 ;[1]",
|
||||||
|
"null 2 null 4 ;[null, 2, null, 4]"
|
||||||
|
})
|
||||||
|
void testAdd(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3",
|
||||||
|
"1 2",
|
||||||
|
"null null"
|
||||||
|
})
|
||||||
|
void testClear(String input) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
array.clear();
|
||||||
|
assertEquals("[]", array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testClearEmpty() {
|
||||||
|
array.clear();
|
||||||
|
assertEquals("[]", array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 null ;4",
|
||||||
|
})
|
||||||
|
void testSize(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
int expected = Integer.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, array.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Array methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;2 ;3",
|
||||||
|
"1 2 3 ;1 ;2",
|
||||||
|
"1 2 3 ;0 ;1",
|
||||||
|
"null null ;0 ;null",
|
||||||
|
"null null ;1 ;null",
|
||||||
|
})
|
||||||
|
void testGet(String input, String indexStr, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
int index = Integer.parseInt(indexStr);
|
||||||
|
assertEquals(expected, array.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 2 ;2 ;1",
|
||||||
|
"1 1 1 ;1 ;0",
|
||||||
|
"1 2 3 ;3 ;2",
|
||||||
|
"null null ;null ;0",
|
||||||
|
"1 null ;null ;1",
|
||||||
|
})
|
||||||
|
void testIndexOf(String input, String xStr, String expectedStr) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
String x = xStr;
|
||||||
|
int expected = Integer.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, array.indexOf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;0 ;[2, 3]",
|
||||||
|
"1 2 3 ;1 ;[1, 3]",
|
||||||
|
"1 2 3 ;2 ;[1, 2]",
|
||||||
|
"null 2 null ;0 ;[2, null]",
|
||||||
|
"1 null ;1 ;[1]",
|
||||||
|
})
|
||||||
|
void testRemove(String input, String indexStr, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
int index = Utils.parseInt(indexStr);
|
||||||
|
array.remove(index);
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;0 ;7 ;[7, 2, 3]",
|
||||||
|
"1 2 3 ;1 ;8 ;[1, 8, 3]",
|
||||||
|
"1 2 3 ;2 ;null ;[1, 2, null]",
|
||||||
|
"null 2 null ;2 ;null ;[null, 2, null]",
|
||||||
|
"null 2 null ;1 ;null ;[null, null, null]",
|
||||||
|
})
|
||||||
|
void testSet(String input, String indexStr, String xStr, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
int index = Integer.parseInt(indexStr);
|
||||||
|
array.set(index, xStr);
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Iterator methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;2",
|
||||||
|
"null 3 ;3",
|
||||||
|
"1 null 3 ;null",
|
||||||
|
"null null ;null"
|
||||||
|
})
|
||||||
|
void testIteratorNext(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
Iterator<String> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;true",
|
||||||
|
"null 3 ;false",
|
||||||
|
"1 null ;false"
|
||||||
|
})
|
||||||
|
void testIteratorHasNext(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
Boolean expected = Utils.parseBoolean(expectedStr);
|
||||||
|
Iterator<String> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[3]",
|
||||||
|
"null null null ;[null]",
|
||||||
|
"null null ;[]",
|
||||||
|
})
|
||||||
|
void testIteratorRemove(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
Iterator<String> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
assertEquals(expected, array.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1",
|
||||||
|
"1 2" ,
|
||||||
|
"null null null",
|
||||||
|
})
|
||||||
|
void testIteratorRemoveShouldThrowException(String input) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
Iterator<String> it1 = array.iterator();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it1.remove());
|
||||||
|
Iterator<String> it2 = array.iterator();
|
||||||
|
it2.next();
|
||||||
|
it2.remove();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it2.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2",
|
||||||
|
"null null",
|
||||||
|
})
|
||||||
|
void testIteratorNextShouldThrowsException(String input) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
Iterator<String> it = array.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertThrows(NoSuchElementException.class, () -> it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;12",
|
||||||
|
"1 null 3 ;1null3",
|
||||||
|
})
|
||||||
|
void testIteratorForEach(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String x : array) {
|
||||||
|
sb.append(x);
|
||||||
|
}
|
||||||
|
String actual = sb.toString();
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Stream methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 4 ;24",
|
||||||
|
"11 22 33 444 ;22444",
|
||||||
|
})
|
||||||
|
void testStreamFilter(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
if (expected == null) {
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
array.stream()
|
||||||
|
.filter(x -> Integer.parseInt(x) % 2 == 0)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"a as asd asdf ;1234",
|
||||||
|
"a asd asdf ;134",
|
||||||
|
"a ;1",
|
||||||
|
})
|
||||||
|
void testStreamMap(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
array.stream()
|
||||||
|
.map(String::length)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"a bc def ghij ;ABD",
|
||||||
|
"a def ;AD",
|
||||||
|
"a ;A",
|
||||||
|
})
|
||||||
|
void testStreamMapFilter(String input, String expected) {
|
||||||
|
Array<String> array = new ArrayImpl<>();
|
||||||
|
Utils.fillInWithStrings(array, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
array.stream()
|
||||||
|
.filter(s -> s.length() <= 3)
|
||||||
|
.map(String::toUpperCase)
|
||||||
|
.map(s -> s.charAt(0))
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"a bc def ghij ;ABD",
|
||||||
|
"a def ;AD",
|
||||||
|
"a ;A",
|
||||||
|
})
|
||||||
|
void testStreamFilterWildcard(String input, String expected) {
|
||||||
|
Array<CharSequence> array = new ArrayImpl<>();
|
||||||
|
Utils.fillIn(array, input, s -> (CharSequence)s);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
array.stream()
|
||||||
|
.filter(s -> s.length() <= 3)
|
||||||
|
.map(s -> s.charAt(0))
|
||||||
|
.map(Object::toString)
|
||||||
|
.map(String::toUpperCase)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class Base {
|
||||||
|
|
||||||
|
{
|
||||||
|
if (ComplianceTest.MAKE_ALL_TESTS_FAILED) {
|
||||||
|
Assertions.fail("Compliance tests have not been passed", ComplianceTest.CAUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import spoon.Launcher;
|
||||||
|
import spoon.SpoonAPI;
|
||||||
|
import spoon.reflect.declaration.CtType;
|
||||||
|
import spoon.reflect.reference.CtTypeReference;
|
||||||
|
import spoon.reflect.visitor.filter.TypeFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
@Disabled("This test is used as a trigger to fail all the other tests")
|
||||||
|
class ComplianceTest {
|
||||||
|
|
||||||
|
// Assign this option to false to skip the compliance test
|
||||||
|
// Note, during testing at the stand this option will be turned on!!!
|
||||||
|
// private static final boolean TURN_TEST_COMPLIANCE_ON = false;
|
||||||
|
private static final boolean TURN_TEST_COMPLIANCE_ON = true;
|
||||||
|
|
||||||
|
public static final boolean MAKE_ALL_TESTS_FAILED;
|
||||||
|
|
||||||
|
public static final Throwable CAUSE;
|
||||||
|
|
||||||
|
private static final Object EOL = System.lineSeparator();
|
||||||
|
|
||||||
|
static {
|
||||||
|
L: {
|
||||||
|
try {
|
||||||
|
if (TURN_TEST_COMPLIANCE_ON) {
|
||||||
|
initSpoon();
|
||||||
|
startCompianceTests();
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
MAKE_ALL_TESTS_FAILED = true;
|
||||||
|
CAUSE = ex.getCause();
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
MAKE_ALL_TESTS_FAILED = false;
|
||||||
|
CAUSE = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SpoonAPI spoon;
|
||||||
|
|
||||||
|
private static void initSpoon() {
|
||||||
|
spoon = new Launcher();
|
||||||
|
spoon.addInputResource("src/main/java/");
|
||||||
|
spoon.buildModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void startCompianceTests() throws ReflectiveOperationException {
|
||||||
|
ComplianceTest cTest = new ComplianceTest();
|
||||||
|
for (Method m : ComplianceTest.class.getDeclaredMethods()) {
|
||||||
|
if (Modifier.isPrivate(m.getModifiers())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Test[] ar = m.getAnnotationsByType(Test.class);
|
||||||
|
if (ar.length > 0 && m.getAnnotationsByType(Test.class)[0] != null) {
|
||||||
|
m.invoke(cTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void appShouldNotUseForbiddenAPI() throws IOException, URISyntaxException {
|
||||||
|
URL url = getClass().getResource("forbidden-api-regex.txt");
|
||||||
|
String regex = Files.readString(Path.of(url.toURI()));
|
||||||
|
Pattern forbiddenAPIRegex = Pattern.compile(regex.toString());
|
||||||
|
StringBuilder errorMessage = new StringBuilder();
|
||||||
|
for (CtType<?> ctType : spoon.getModel().getAllTypes()) {
|
||||||
|
List<String> forbiddenAPI = ctType.getElements(new TypeFilter<>(CtTypeReference.class))
|
||||||
|
.stream()
|
||||||
|
.distinct()
|
||||||
|
.filter(r -> forbiddenAPIRegex.matcher(r.toString()).matches())
|
||||||
|
.map(CtTypeReference::getQualifiedName)
|
||||||
|
.toList();
|
||||||
|
if (!forbiddenAPI.isEmpty()) {
|
||||||
|
errorMessage.append(EOL)
|
||||||
|
.append(ctType.getQualifiedName()).append(": ")
|
||||||
|
.append(forbiddenAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!errorMessage.isEmpty()) {
|
||||||
|
fail(() -> "Using of this API is forbidden: " + errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeAppropriateNumberOfPackagesAndClasses() throws IOException, URISyntaxException {
|
||||||
|
URL url = getClass().getResource("list-of-types.txt");
|
||||||
|
String expected = Files.readString(Path.of(url.toURI()));
|
||||||
|
// '\n' character is used for clarity in error message
|
||||||
|
String actual = spoon.getModel().getAllPackages().stream()
|
||||||
|
.filter(p -> p.getTypes().size() != 0)
|
||||||
|
.map(p -> p.getTypes().stream()
|
||||||
|
.map(CtType::getQualifiedName)
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining("\n")))
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
assertEquals('\n' + expected.stripTrailing(), '\n' + actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,312 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class ListImplIntegerTest extends Base {
|
||||||
|
|
||||||
|
private List<Integer> list = new ListImpl<>();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Container methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[1, 2, 3]",
|
||||||
|
"1 ;[1]",
|
||||||
|
"null 2 null 4 ;[null, 2, null, 4]"
|
||||||
|
})
|
||||||
|
void testAdd(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3",
|
||||||
|
"1 2",
|
||||||
|
"null null"
|
||||||
|
})
|
||||||
|
void testClear(String input) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
list.clear();
|
||||||
|
assertEquals("[]", list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testClearEmpty() {
|
||||||
|
list.clear();
|
||||||
|
assertEquals("[]", list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 null ;4",
|
||||||
|
})
|
||||||
|
void testSize(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
int expected = Integer.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// List methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 2 ;1",
|
||||||
|
"2 1 1 ;2",
|
||||||
|
"null 2 ;null",
|
||||||
|
})
|
||||||
|
void testGetFirst(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Integer expected = Utils.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, list.getFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 2 ;2",
|
||||||
|
"2 1 1 ;1",
|
||||||
|
"1 null ;null",
|
||||||
|
})
|
||||||
|
void testGetLast(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Integer expected = Utils.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, list.getLast());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[2, 3]",
|
||||||
|
"null 1 2 ;[1, 2]",
|
||||||
|
"null ;[]",
|
||||||
|
"1 ;[]",
|
||||||
|
})
|
||||||
|
void testRemoveFirst(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
list.removeFirst();
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[1, 2]",
|
||||||
|
"null 2 3 ;[null, 2]",
|
||||||
|
"null ;[]",
|
||||||
|
"1 ;[]",
|
||||||
|
})
|
||||||
|
void testRemoveLast(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
list.removeLast();
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;7 ;[7, 1, 2, 3]",
|
||||||
|
"1 2 3 ;null ;[null, 1, 2, 3]",
|
||||||
|
"null 2 null ;null ;[null, null, 2, null]",
|
||||||
|
})
|
||||||
|
void testAddFirst(String input, String xStr, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Integer x = Utils.parseInt(xStr);
|
||||||
|
list.addFirst(x);
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;7 ;null",
|
||||||
|
"1 2 3 ;3 ;3",
|
||||||
|
"null 2 null ;null ;null",
|
||||||
|
})
|
||||||
|
void testSearch(String input, String xStr, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Integer x = Utils.parseInt(xStr);
|
||||||
|
Integer expected = Utils.parseInt(expectedStr);
|
||||||
|
Integer actual = list.search(x);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;7 ;[1, 2, 3] ;false",
|
||||||
|
"1 2 3 ;2 ;[1, 3] ;true",
|
||||||
|
"1 2 3 ;3 ;[1, 2] ;true",
|
||||||
|
"null 2 null ;null ;[2, null] ;true",
|
||||||
|
})
|
||||||
|
void testRemove(String input, String xStr, String expected, String isExistStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Integer x = Utils.parseInt(xStr);
|
||||||
|
boolean isExistActual = list.remove(x);
|
||||||
|
boolean isExistExpected = Utils.parseBoolean(isExistStr);
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
assertEquals(isExistExpected, isExistActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Iterator methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;2",
|
||||||
|
"null 3 ;3",
|
||||||
|
"1 null 3 ;null",
|
||||||
|
"null null ;null"
|
||||||
|
})
|
||||||
|
void testIteratorNext(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Iterator<Integer> it = list.iterator();
|
||||||
|
Integer expected = Utils.parseInt(expectedStr);
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;true",
|
||||||
|
"null 3 ;false",
|
||||||
|
"1 null ;false"
|
||||||
|
})
|
||||||
|
void testIteratorHasNext(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Boolean expected = Utils.parseBoolean(expectedStr);
|
||||||
|
Iterator<Integer> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[3]",
|
||||||
|
"null null null ;[null]",
|
||||||
|
})
|
||||||
|
void testIteratorRemove(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Iterator<Integer> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1",
|
||||||
|
"1 2" ,
|
||||||
|
"null null null",
|
||||||
|
})
|
||||||
|
void testIteratorRemoveShouldThrowException(String input) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Iterator<Integer> it1 = list.iterator();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it1.remove());
|
||||||
|
Iterator<Integer> it2 = list.iterator();
|
||||||
|
it2.next();
|
||||||
|
it2.remove();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it2.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2",
|
||||||
|
"null null",
|
||||||
|
})
|
||||||
|
void testIteratorNextShouldThrowsException(String input) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
Iterator<Integer> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertThrows(NoSuchElementException.class, () -> it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;12",
|
||||||
|
"1 null 3 ;1null3",
|
||||||
|
})
|
||||||
|
void testIteratorForEach(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Integer x : list) {
|
||||||
|
sb.append(x);
|
||||||
|
}
|
||||||
|
String actual = sb.toString();
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Stream methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 4 ;24",
|
||||||
|
})
|
||||||
|
void testStreamFilter(String input, String expected) {
|
||||||
|
Utils.fillInWithIntegers(list, input);
|
||||||
|
if (expected == null) {
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
list.stream()
|
||||||
|
.filter(x -> x % 2 == 0)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 4 ;++|++++|",
|
||||||
|
"2 3 4 ;++|++++|",
|
||||||
|
"2 ;++|",
|
||||||
|
})
|
||||||
|
void testStreamFilterWildcard(String input, String expected) {
|
||||||
|
Utils.fillIn(list, input, Integer::parseInt);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
list.stream()
|
||||||
|
.filter(x -> x % 2 == 0)
|
||||||
|
.map(x -> "+".repeat(x))
|
||||||
|
.forEach(x -> sb.append(x).append('|'));
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,354 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
class ListImplStringTest extends Base {
|
||||||
|
|
||||||
|
private List<String> list = new ListImpl<>();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Container methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[1, 2, 3]",
|
||||||
|
"1 ;[1]",
|
||||||
|
"null 2 null 4 ;[null, 2, null, 4]",
|
||||||
|
"a b c ;[a, b, c]",
|
||||||
|
"1 b null ;[1, b, null]",
|
||||||
|
})
|
||||||
|
void testAdd(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3",
|
||||||
|
"1 2",
|
||||||
|
"null null"
|
||||||
|
})
|
||||||
|
void testClear(String input) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
list.clear();
|
||||||
|
assertEquals("[]", list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testClearEmpty() {
|
||||||
|
list.clear();
|
||||||
|
assertEquals("[]", list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 null ;4",
|
||||||
|
})
|
||||||
|
void testSize(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
int expected = Integer.parseInt(expectedStr);
|
||||||
|
assertEquals(expected, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// List methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 2 ;1",
|
||||||
|
"2 1 1 ;2",
|
||||||
|
"null 2 ;null",
|
||||||
|
})
|
||||||
|
void testGetFirst(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
assertEquals(expected, list.getFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 2 ;2",
|
||||||
|
"2 1 1 ;1",
|
||||||
|
"1 null ;null",
|
||||||
|
})
|
||||||
|
void testGetLast(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
assertEquals(expected, list.getLast());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[2, 3]",
|
||||||
|
"null 1 2 ;[1, 2]",
|
||||||
|
"null ;[]",
|
||||||
|
"1 ;[]",
|
||||||
|
})
|
||||||
|
void testRemoveFirst(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
list.removeFirst();
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[1, 2]",
|
||||||
|
"null 2 3 ;[null, 2]",
|
||||||
|
"null ;[]",
|
||||||
|
"1 ;[]",
|
||||||
|
})
|
||||||
|
void testRemoveLast(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
list.removeLast();
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;7 ;[7, 1, 2, 3]",
|
||||||
|
"1 2 3 ;null ;[null, 1, 2, 3]",
|
||||||
|
"null 2 null ;null ;[null, null, 2, null]",
|
||||||
|
})
|
||||||
|
void testAddFirst(String input, String xStr, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
list.addFirst(xStr);
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;7 ;null",
|
||||||
|
"1 2 3 ;3 ;3",
|
||||||
|
"null 2 null ;null ;null",
|
||||||
|
})
|
||||||
|
void testSearch(String input, String xStr, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
String x = xStr;
|
||||||
|
if (x != null && "null".equals(x)) {
|
||||||
|
x = null;
|
||||||
|
}
|
||||||
|
if ("null".equals(expected)) {
|
||||||
|
expected = null;
|
||||||
|
}
|
||||||
|
String actual = list.search(x);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;7 ;[1, 2, 3] ;false",
|
||||||
|
"1 2 3 ;2 ;[1, 3] ;true",
|
||||||
|
"1 2 3 ;3 ;[1, 2] ;true",
|
||||||
|
"null 2 null ;null ;[2, null] ;true",
|
||||||
|
})
|
||||||
|
void testRemove(String input, String xStr, String expected, String isExistStr) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
String x = xStr;
|
||||||
|
boolean isExistActual = list.remove(x);
|
||||||
|
boolean isExistExpected = Utils.parseBoolean(isExistStr);
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
assertEquals(isExistExpected, isExistActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Iterator methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;2",
|
||||||
|
"null 3 ;3",
|
||||||
|
"1 null 3 ;null",
|
||||||
|
"null null ;null"
|
||||||
|
})
|
||||||
|
void testIteratorNext(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
Iterator<String> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;true",
|
||||||
|
"null 3 ;false",
|
||||||
|
"1 null ;false"
|
||||||
|
})
|
||||||
|
void testIteratorHasNext(String input, String expectedStr) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
Boolean expected = Utils.parseBoolean(expectedStr);
|
||||||
|
Iterator<String> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertEquals(expected, it.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2 3 ;[3]",
|
||||||
|
"null null null ;[null]",
|
||||||
|
})
|
||||||
|
void testIteratorRemove(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
Iterator<String> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
assertEquals(expected, list.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1",
|
||||||
|
"1 2" ,
|
||||||
|
"null null null",
|
||||||
|
})
|
||||||
|
void testIteratorRemoveShouldThrowException(String input) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
Iterator<String> it1 = list.iterator();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it1.remove());
|
||||||
|
Iterator<String> it2 = list.iterator();
|
||||||
|
it2.next();
|
||||||
|
it2.remove();
|
||||||
|
assertThrows(IllegalStateException.class, () -> it2.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 2",
|
||||||
|
"null null",
|
||||||
|
})
|
||||||
|
void testIteratorNextShouldThrowsException(String input) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
Iterator<String> it = list.iterator();
|
||||||
|
it.next();
|
||||||
|
it.next();
|
||||||
|
assertThrows(NoSuchElementException.class, () -> it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;1",
|
||||||
|
"1 2 ;12",
|
||||||
|
"1 null 3 ;1null3",
|
||||||
|
})
|
||||||
|
void testIteratorForEach(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String x : list) {
|
||||||
|
sb.append(x);
|
||||||
|
}
|
||||||
|
String actual = sb.toString();
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Stream methods.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"1 ;",
|
||||||
|
"1 2 ;2",
|
||||||
|
"1 2 3 4 ;24",
|
||||||
|
})
|
||||||
|
void testStreamFilter(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
if (expected == null) {
|
||||||
|
expected = "";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
list.stream()
|
||||||
|
.filter(x -> Utils.parseInt(x) % 2 == 0)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"a as asd asdf ;1234",
|
||||||
|
"a asd asdf ;134",
|
||||||
|
"a ;1",
|
||||||
|
})
|
||||||
|
|
||||||
|
void testStreamMap(String input, String expected) {
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
list.stream()
|
||||||
|
.map(String::length)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"a bc def ghij ;ABD",
|
||||||
|
"a def ;AD",
|
||||||
|
"a ;A",
|
||||||
|
})
|
||||||
|
void testStreamMapFilter(String input, String expected) {
|
||||||
|
Array<String> list = new ArrayImpl<>();
|
||||||
|
Utils.fillInWithStrings(list, input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
list.stream()
|
||||||
|
.filter(s -> s.length() <= 3)
|
||||||
|
.map(String::toUpperCase)
|
||||||
|
.map(s -> s.charAt(0))
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest()
|
||||||
|
@CsvSource(delimiter = ';',
|
||||||
|
value = {
|
||||||
|
"a bc def ghij ;ABD",
|
||||||
|
"a def ;AD",
|
||||||
|
"a ;A",
|
||||||
|
})
|
||||||
|
void testStreamFilterWildcard(String input, String expected) {
|
||||||
|
Array<CharSequence> list = new ArrayImpl<>();
|
||||||
|
Utils.fillIn(list, input, s -> (CharSequence)s);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
list.stream()
|
||||||
|
.filter(s -> s.length() <= 3)
|
||||||
|
.map(s -> s.charAt(0))
|
||||||
|
.map(Object::toString)
|
||||||
|
.map(String::toUpperCase)
|
||||||
|
.forEach(sb::append);
|
||||||
|
assertEquals(expected, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package ua.nure.jfn.task2;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmytro Kolesnykov
|
||||||
|
*/
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
public static <T extends Container<Integer>> void fillInWithIntegers(T container, String input) {
|
||||||
|
fillIn(container, input, Utils::parseInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Container<String>> void fillInWithStrings(T container, String input) {
|
||||||
|
fillIn(container, input, Function.identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E, T extends Container<E>> void fillIn(T container, String input, Function<String, E> func) {
|
||||||
|
Arrays.stream(input.split("\\s+"))
|
||||||
|
.map(func)
|
||||||
|
.forEach(container::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer parseInt(String str) {
|
||||||
|
return "null".equals(str) ? null : Integer.valueOf(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean parseBoolean(String str) {
|
||||||
|
return "null".equals(str) ? null : Boolean.valueOf(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
(?x)
|
||||||
|
^
|
||||||
|
java\.util\.(?!Arrays|Iterator|NoSuchElementException)\S+
|
||||||
|
$
|
@ -0,0 +1,8 @@
|
|||||||
|
ua.nure.jfn.task2.Array
|
||||||
|
ua.nure.jfn.task2.ArrayImpl
|
||||||
|
ua.nure.jfn.task2.Container
|
||||||
|
ua.nure.jfn.task2.Demo
|
||||||
|
ua.nure.jfn.task2.List
|
||||||
|
ua.nure.jfn.task2.ListImpl
|
||||||
|
ua.nure.jfn.task2.Stream
|
||||||
|
ua.nure.jfn.task2.StreamImpl
|
BIN
semester-4/ОПJа/lb-2/tasks.pdf
Normal file
5
semester-4/ОС/lb-1/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Викладач: Мельникова Р. В.
|
||||||
|
Оцінка: 87
|
||||||
|
|
||||||
|
Додатково:
|
||||||
|
Завдання на максимальний бал із віддзеркаленням рядків виконано для UTF-8 замість UTF-16.
|
BIN
semester-4/ОС/lb-1/img/task1/main.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
semester-4/ОС/lb-1/img/task1/make.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
semester-4/ОС/lb-1/img/task10/main.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
semester-4/ОС/lb-1/img/task11/main.png
Normal file
After Width: | Height: | Size: 127 KiB |
BIN
semester-4/ОС/lb-1/img/task11/result.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
semester-4/ОС/lb-1/img/task12/codepage.png
Normal file
After Width: | Height: | Size: 182 KiB |
BIN
semester-4/ОС/lb-1/img/task12/resultA.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
semester-4/ОС/lb-1/img/task12/resultU.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
semester-4/ОС/lb-1/img/task12/rfile.png
Normal file
After Width: | Height: | Size: 398 KiB |
BIN
semester-4/ОС/lb-1/img/task12/rstr.png
Normal file
After Width: | Height: | Size: 250 KiB |
BIN
semester-4/ОС/lb-1/img/task2/main.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
semester-4/ОС/lb-1/img/task2/result.png
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
semester-4/ОС/lb-1/img/task4/make.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
semester-4/ОС/lb-1/img/task5/result.png
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
semester-4/ОС/lb-1/img/task6/main.png
Normal file
After Width: | Height: | Size: 274 KiB |
BIN
semester-4/ОС/lb-1/img/task6/result.png
Normal file
After Width: | Height: | Size: 209 KiB |
BIN
semester-4/ОС/lb-1/img/task7/main.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
semester-4/ОС/lb-1/img/task7/result.png
Normal file
After Width: | Height: | Size: 273 KiB |
BIN
semester-4/ОС/lb-1/img/task8/main.png
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
semester-4/ОС/lb-1/img/task8/msg1.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
semester-4/ОС/lb-1/img/task8/msg2.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
semester-4/ОС/lb-1/img/task8/msg3.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
semester-4/ОС/lb-1/img/task8/result.png
Normal file
After Width: | Height: | Size: 437 KiB |
BIN
semester-4/ОС/lb-1/img/task9/main.png
Normal file
After Width: | Height: | Size: 381 KiB |
BIN
semester-4/ОС/lb-1/img/task9/qsort.png
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
semester-4/ОС/lb-1/img/task9/result.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
semester-4/ОС/lb-1/img/task9/sort.png
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
semester-4/ОС/lb-1/img/task9/strcp.png
Normal file
After Width: | Height: | Size: 182 KiB |
692
semester-4/ОС/lb-1/lib.typ
Normal file
@ -0,0 +1,692 @@
|
|||||||
|
|
||||||
|
// Academic aliases {{{1
|
||||||
|
|
||||||
|
/// subject abbreviations to full names
|
||||||
|
#let subjects = (
|
||||||
|
"БД": "Бази даних",
|
||||||
|
"ОПНJ": "Основи програмування на Java",
|
||||||
|
"ОС": "Операційні системи",
|
||||||
|
"ПП": "Проектний практикум",
|
||||||
|
"СПМ": "Скриптові мови програмування",
|
||||||
|
"Ф": "Філософія",
|
||||||
|
)
|
||||||
|
|
||||||
|
/// education program abbreviations to name & number
|
||||||
|
#let edu_programs = (
|
||||||
|
"ПЗПІ": (
|
||||||
|
name: "Інженерія програмного забезпечення",
|
||||||
|
number: 121, // TODO: ПЗПІ is "F2" now
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Template formatting functions {{{1
|
||||||
|
|
||||||
|
/// numberless heading
|
||||||
|
#let nheading(title) = heading(depth: 1, numbering: none, title)
|
||||||
|
|
||||||
|
/// fill horizontal space with a box and not an empty space
|
||||||
|
#let hfill(width) = box(width: width, repeat(" ")) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
|
||||||
|
|
||||||
|
/// make underlined cell with filled value
|
||||||
|
#let uline(align: center, content) = underline[
|
||||||
|
#if align != left { hfill(1fr) }
|
||||||
|
#content
|
||||||
|
#if align != right { hfill(1fr) }
|
||||||
|
]
|
||||||
|
|
||||||
|
/// bold text
|
||||||
|
#let bold(content) = text(weight: "bold")[#content]
|
||||||
|
|
||||||
|
/// month name from its number
|
||||||
|
#let month_gen(month) = (
|
||||||
|
"січня",
|
||||||
|
"лютого",
|
||||||
|
"березня",
|
||||||
|
"квітня",
|
||||||
|
"травня",
|
||||||
|
"червня",
|
||||||
|
"липня",
|
||||||
|
"серпня",
|
||||||
|
"вересня",
|
||||||
|
"жовтня",
|
||||||
|
"листопада",
|
||||||
|
"грудня",
|
||||||
|
).at(month - 1)
|
||||||
|
|
||||||
|
// Helper functions {{{1
|
||||||
|
|
||||||
|
/// captioned image with label derived from path:
|
||||||
|
/// - "image.png" = @image
|
||||||
|
/// - "img/image.png" = @image
|
||||||
|
/// - "img/foo/image.png" = @foo_image
|
||||||
|
/// - "img/foo/foo_image.png" = @foo_image
|
||||||
|
/// the caption will be modified based on a conditional positional value:
|
||||||
|
/// - `none`: no change
|
||||||
|
/// - some value: "`caption` (за даними `value`)"
|
||||||
|
/// - no value: "`caption` (рисунок виконано самостійно)"
|
||||||
|
/// additional named arguments will be passed to original `image` function
|
||||||
|
#let img(path, caption, ..sink) = {
|
||||||
|
let parts = path.split(".").first().split("/")
|
||||||
|
|
||||||
|
let label_string = if parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2)) {
|
||||||
|
// ("image",), (_, "image") and (.., "img", "img_image")
|
||||||
|
parts.last()
|
||||||
|
} else {
|
||||||
|
// (.., "img", "image") = "img_image"
|
||||||
|
parts.at(-2) + "_" + parts.at(-1)
|
||||||
|
}.replace(" ", "_")
|
||||||
|
|
||||||
|
let caption = if sink.pos().len() == 0 {
|
||||||
|
caption + " (рисунок виконано самостійно)"
|
||||||
|
} else if sink.pos().first() == none {
|
||||||
|
caption
|
||||||
|
} else {
|
||||||
|
[#caption (за даними #sink.pos().first())]
|
||||||
|
}
|
||||||
|
|
||||||
|
[#figure(image(path, ..sink.named()), caption: caption) #label(label_string)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styling {{{1
|
||||||
|
/// NOTE: may be wrong
|
||||||
|
#let ua_alpha_numbering = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а"
|
||||||
|
|
||||||
|
// general outlook {{{2
|
||||||
|
// spacing between lines
|
||||||
|
#let spacing = 0.95em
|
||||||
|
|
||||||
|
#let style(it) = {
|
||||||
|
set page(
|
||||||
|
paper: "a4",
|
||||||
|
margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm),
|
||||||
|
number-align: top + right,
|
||||||
|
numbering: (..numbers) => {
|
||||||
|
if numbers.pos().at(0) != 1 {
|
||||||
|
numbering("1", numbers.pos().at(0))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
set text(font: ("Times New Roman", "Liberation Serif"), size: 14pt, hyphenate: false, lang: "uk")
|
||||||
|
set par(justify: true, first-line-indent: (amount: 1.25cm, all: true))
|
||||||
|
set underline(evade: false)
|
||||||
|
|
||||||
|
// set 1.5 line spacing
|
||||||
|
set block(spacing: spacing)
|
||||||
|
set par(spacing: spacing)
|
||||||
|
set par(leading: spacing)
|
||||||
|
|
||||||
|
// enums and lists {{{2
|
||||||
|
set enum(numbering: i => { ua_alpha_numbering.at(i) + ")" }, indent: 1.25cm, body-indent: 0.5cm)
|
||||||
|
show enum: it => {
|
||||||
|
set enum(indent: 0em, numbering: "1)")
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--])
|
||||||
|
|
||||||
|
// figures {{{2
|
||||||
|
show figure: it => {
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
it
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
set figure.caption(separator: [ -- ])
|
||||||
|
show figure.where(kind: table): set figure.caption(position: top)
|
||||||
|
show figure.caption.where(kind: table): set align(left)
|
||||||
|
|
||||||
|
// figure numbering
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
counter(math.equation).update(0)
|
||||||
|
counter(figure.where(kind: image)).update(0)
|
||||||
|
counter(figure.where(kind: table)).update(0)
|
||||||
|
counter(figure.where(kind: raw)).update(0)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
set math.equation(numbering: (..num) => numbering("(1.1)", counter(heading).get().at(0), num.pos().first()))
|
||||||
|
set figure(numbering: (..num) => numbering("1.1", counter(heading).get().at(0), num.pos().first()))
|
||||||
|
|
||||||
|
// appearance of references to images and tables {{{2
|
||||||
|
set ref(
|
||||||
|
supplement: it => {
|
||||||
|
if it == none or not it.has("kind") {
|
||||||
|
it
|
||||||
|
} else if it.kind == image {
|
||||||
|
"див. рис."
|
||||||
|
} else if it.kind == table {
|
||||||
|
"див. таблицю"
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
show ref: it => {
|
||||||
|
let el = it.element
|
||||||
|
|
||||||
|
if el == none or not el.has("kind") {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
if el.kind != image and el.kind != table {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
[(#it)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// headings {{{2
|
||||||
|
set heading(numbering: "1.1")
|
||||||
|
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "semibold")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
upper(it)
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
show heading.where(level: 2): it => {
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
block(width: 100%, spacing: 0em)[
|
||||||
|
#h(1.25cm)
|
||||||
|
#counter(heading).display(it.numbering)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 3): it => {
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
block(width: 100%, spacing: 0em)[
|
||||||
|
#h(1.25cm)
|
||||||
|
#counter(heading).display(it.numbering)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coursework template {{{1
|
||||||
|
|
||||||
|
/// DSTU 3008:2015 Template for NURE
|
||||||
|
/// -> content
|
||||||
|
/// - doc (content): Content to apply the template to.
|
||||||
|
/// - title (str): Title of the document.
|
||||||
|
/// - subject_shorthand (str): Subject short name.
|
||||||
|
/// - department_gen (str): Department name in genitive form.
|
||||||
|
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||||
|
/// - mentors ((name: str, gender: str, degree: str),): List of mentors dicts.
|
||||||
|
/// - edu_program_shorthand (str): Education program shorthand.
|
||||||
|
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
|
||||||
|
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
|
||||||
|
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
|
||||||
|
/// - bib_path path: Path to the bibliography yaml file.
|
||||||
|
/// - appendices (content): Content with appendices.
|
||||||
|
#let cw-template(
|
||||||
|
doc,
|
||||||
|
title: "NONE",
|
||||||
|
subject_shorthand: "NONE",
|
||||||
|
department_gen: "Програмної інженерії",
|
||||||
|
author: (),
|
||||||
|
mentors: (),
|
||||||
|
edu_program_shorthand: "ПЗПІ",
|
||||||
|
task_list: (),
|
||||||
|
calendar_plan: (),
|
||||||
|
abstract: (),
|
||||||
|
bib_path: "bibl.yml",
|
||||||
|
appendices: (),
|
||||||
|
) = {
|
||||||
|
set document(title: title, author: author.name)
|
||||||
|
|
||||||
|
show: style
|
||||||
|
|
||||||
|
let bib-count = state("citation-counter", ())
|
||||||
|
show cite: it => {
|
||||||
|
it
|
||||||
|
bib-count.update(((..c)) => (..c, it.key))
|
||||||
|
}
|
||||||
|
show bibliography: it => {
|
||||||
|
set text(size: 0pt)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let head_mentor = mentors.at(0)
|
||||||
|
let edu_program = edu_programs.at(edu_program_shorthand)
|
||||||
|
|
||||||
|
// page 1 {{{2
|
||||||
|
[
|
||||||
|
#set align(center)
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
|
||||||
|
|
||||||
|
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
Кафедра Програмної інженерії
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
ПОЯСНЮВАЛЬНА ЗАПИСКА
|
||||||
|
|
||||||
|
ДО КУРСОВОЇ РОБОТИ
|
||||||
|
|
||||||
|
з дисципліни: "#subjects.at(subject_shorthand, default: "NONE")"
|
||||||
|
|
||||||
|
Тема роботи: "#title"
|
||||||
|
|
||||||
|
\ \ \
|
||||||
|
|
||||||
|
#columns(2, gutter: 4cm)[
|
||||||
|
#set align(left)
|
||||||
|
|
||||||
|
#if author.gender == "m" { [Виконав\ ] } else { [Виконала\ ] } ст. гр. #author.group
|
||||||
|
|
||||||
|
\
|
||||||
|
Керівник:\
|
||||||
|
#head_mentor.degree
|
||||||
|
|
||||||
|
\
|
||||||
|
Робота захищена на оцінку
|
||||||
|
|
||||||
|
\
|
||||||
|
Комісія:\
|
||||||
|
#for mentor in mentors {
|
||||||
|
[#mentor.degree\
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#colbreak()
|
||||||
|
#set align(left)
|
||||||
|
|
||||||
|
\
|
||||||
|
#author.name
|
||||||
|
|
||||||
|
\ \
|
||||||
|
#head_mentor.name
|
||||||
|
|
||||||
|
\
|
||||||
|
#underline(" " * 35)
|
||||||
|
|
||||||
|
\ \
|
||||||
|
#for mentor in mentors {
|
||||||
|
[#mentor.name\
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
Харків -- #task_list.done_date.display("[year]")
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
]
|
||||||
|
|
||||||
|
// page 2 {{{2
|
||||||
|
{
|
||||||
|
uline[Харківський національний університет радіоелектроніки]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: (100pt, 1fr),
|
||||||
|
bold[
|
||||||
|
Кафедра
|
||||||
|
Дисципліна
|
||||||
|
Спеціальність
|
||||||
|
],
|
||||||
|
{
|
||||||
|
uline(align: left, department_gen)
|
||||||
|
linebreak()
|
||||||
|
uline(align: left, subjects.at(subject_shorthand))
|
||||||
|
linebreak()
|
||||||
|
uline(align: left, [#edu_program.number #edu_program.name])
|
||||||
|
},
|
||||||
|
)
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 1fr, 1fr),
|
||||||
|
gutter: 0.3fr,
|
||||||
|
[#bold[Курс] #uline(2)], [#bold[Група] #uline(author.group)], [#bold[Семестр] #uline(3)],
|
||||||
|
)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
uline(align: left)[_#author.full_name_gen _]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\1. Тема роботи:]
|
||||||
|
uline[#title.]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
bold[\2. Строк здачі закінченої роботи:]
|
||||||
|
uline(task_list.done_date.display("[day].[month].[year]"))
|
||||||
|
hfill(10fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\3. Вихідні дані для роботи:]
|
||||||
|
uline(task_list.source)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\4. Зміст розрахунково-пояснювальної записки:]
|
||||||
|
uline(task_list.content)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\5. Перелік графічного матеріалу:]
|
||||||
|
uline(task_list.graphics)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
bold[\6. Дата видачі завдання:]
|
||||||
|
uline(task_list.initial_date.display("[day].[month].[year]"))
|
||||||
|
hfill(10fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
// page 3 {{{2
|
||||||
|
{
|
||||||
|
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
calendar_plan.plan_table
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: (5fr, 5fr),
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 2fr, 1fr),
|
||||||
|
gutter: 0.2fr,
|
||||||
|
[
|
||||||
|
Студент \
|
||||||
|
Керівник \
|
||||||
|
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
#uline(align: center, []) \
|
||||||
|
#uline(align: center, []) \
|
||||||
|
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
|
||||||
|
],
|
||||||
|
[
|
||||||
|
\ \
|
||||||
|
#underline[#calendar_plan.approval_date.year()] р.
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
#author.name, \
|
||||||
|
#head_mentor.degree
|
||||||
|
#head_mentor.name.
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
// page 4 {{{2
|
||||||
|
[
|
||||||
|
#align(center, bold[РЕФЕРАТ]) \
|
||||||
|
|
||||||
|
#context [
|
||||||
|
#let pages = counter(page).final().at(0)
|
||||||
|
#let images = query(figure.where(kind: image)).len()
|
||||||
|
#let tables = query(figure.where(kind: table)).len()
|
||||||
|
#let bibs = bib-count.final().dedup().len()
|
||||||
|
/* TODO: why this stopped working?
|
||||||
|
#let tables = counter(figure.where(kind: table)).final().at(0)
|
||||||
|
#let images = counter(figure.where(kind: image)).final().at(0)*/
|
||||||
|
|
||||||
|
#let counters = ()
|
||||||
|
|
||||||
|
#if pages != 0 { counters.push[#pages с.] }
|
||||||
|
#if tables != 0 { counters.push[#tables табл.] }
|
||||||
|
#if images != 0 { counters.push[#images рис.] }
|
||||||
|
#if bibs != 0 { counters.push[#bibs джерел] }
|
||||||
|
|
||||||
|
Пояснювальна записка до курсової роботи: #counters.join(", ").
|
||||||
|
]
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#{
|
||||||
|
let keywords = abstract.keywords.map(upper)
|
||||||
|
let is_cyrillic = word => word.split("").any(char => ("А" <= char and char <= "я"))
|
||||||
|
|
||||||
|
let n = keywords.len()
|
||||||
|
for i in range(n) {
|
||||||
|
for j in range(0, n - i - 1) {
|
||||||
|
if (
|
||||||
|
(not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1)))
|
||||||
|
or (
|
||||||
|
is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
(keywords.at(j), keywords.at(j + 1)) = (keywords.at(j + 1), keywords.at(j))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keywords.join(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#abstract.text
|
||||||
|
]
|
||||||
|
|
||||||
|
// page 5 {{{2
|
||||||
|
outline(
|
||||||
|
title: [
|
||||||
|
ЗМІСТ
|
||||||
|
#v(spacing * 2, weak: true)
|
||||||
|
],
|
||||||
|
depth: 2,
|
||||||
|
indent: auto,
|
||||||
|
)
|
||||||
|
|
||||||
|
doc
|
||||||
|
|
||||||
|
// bibliography {{{2
|
||||||
|
{
|
||||||
|
heading(depth: 1, numbering: none)[Перелік джерел посилання]
|
||||||
|
|
||||||
|
bibliography(
|
||||||
|
bib_path,
|
||||||
|
style: "ieee",
|
||||||
|
full: true,
|
||||||
|
title: none,
|
||||||
|
)
|
||||||
|
|
||||||
|
let bib_data = yaml(bib_path)
|
||||||
|
|
||||||
|
let format-entry(citation) = {
|
||||||
|
if (citation.type == "Web") {
|
||||||
|
let date_array = citation.url.date.split("-")
|
||||||
|
let date = datetime(
|
||||||
|
year: int(date_array.at(0)),
|
||||||
|
month: int(date_array.at(1)),
|
||||||
|
day: int(date_array.at(2)),
|
||||||
|
)
|
||||||
|
[
|
||||||
|
#citation.title.
|
||||||
|
#citation.author.
|
||||||
|
URL: #citation.url.value (дата звернення: #date.display("[day].[month].[year]")).
|
||||||
|
]
|
||||||
|
} else if citation.type == "Book" [
|
||||||
|
#citation.author
|
||||||
|
#citation.title.
|
||||||
|
#citation.publisher,
|
||||||
|
#citation.date.
|
||||||
|
#citation.page-total c.
|
||||||
|
] else [
|
||||||
|
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
show enum.item: it => {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
box(width: 1.25cm)
|
||||||
|
box(width: 1em + 0.5cm)[#it.number.]
|
||||||
|
it.body
|
||||||
|
linebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
context {
|
||||||
|
for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() {
|
||||||
|
enum.item(
|
||||||
|
i + 1,
|
||||||
|
format-entry(bib_data.at(citation)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendices {{{2
|
||||||
|
{
|
||||||
|
counter(heading).update(0)
|
||||||
|
|
||||||
|
set heading(
|
||||||
|
numbering: (i, ..nums) => {
|
||||||
|
let char = upper(ua_alpha_numbering.at(i))
|
||||||
|
if nums.pos().len() == 0 { char } else {
|
||||||
|
char + "." + nums.pos().map(str).join(".")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||||
|
linebreak()
|
||||||
|
it.body
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 2): it => {
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
block(width: 100%, spacing: 0em)[
|
||||||
|
#h(1.25cm)
|
||||||
|
#counter(heading).display(it.numbering)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
appendices
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Laboratory work template {{{1
|
||||||
|
|
||||||
|
/// DSTU 3008:2015 Template for NURE
|
||||||
|
/// -> content
|
||||||
|
/// - doc (content): Content to apply the template to.
|
||||||
|
/// - doctype ("ЛБ" | "ПЗ"): Document type.
|
||||||
|
/// - title (str): Title of the document.
|
||||||
|
/// - subject_shorthand (str): Subject short name.
|
||||||
|
/// - department_gen (str): Department name in genitive form.
|
||||||
|
/// - worknumber (int): Number of the work, can be omitted.
|
||||||
|
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||||
|
/// - mentor (name: str, gender: str, degree: str): Mentors objects.
|
||||||
|
#let lab-pz-template(
|
||||||
|
doc,
|
||||||
|
doctype: "NONE",
|
||||||
|
title: "NONE",
|
||||||
|
subject_shorthand: "NONE",
|
||||||
|
department_gen: "Програмної інженерії",
|
||||||
|
worknumber: 1,
|
||||||
|
authors: (),
|
||||||
|
mentor: (),
|
||||||
|
) = {
|
||||||
|
set document(title: title, author: authors.at(0).name)
|
||||||
|
|
||||||
|
show: style
|
||||||
|
|
||||||
|
context counter(heading).update(worknumber - 1)
|
||||||
|
|
||||||
|
// page 1 {{{2
|
||||||
|
align(center)[
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
|
||||||
|
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||||
|
|
||||||
|
\ \
|
||||||
|
Кафедра #department_gen
|
||||||
|
|
||||||
|
\ \ \
|
||||||
|
Звіт \
|
||||||
|
з
|
||||||
|
#if doctype == "ЛБ" [лабораторної роботи] else [практичної роботи]
|
||||||
|
#if worknumber != none [№ #worknumber]
|
||||||
|
|
||||||
|
з дисципліни: "#subjects.at(subject_shorthand, default: "UNLNOWN SUBJECT, PLEASE OPEN AN ISSUE")"
|
||||||
|
|
||||||
|
з теми: "#title"
|
||||||
|
|
||||||
|
\ \ \ \
|
||||||
|
|
||||||
|
#columns(2)[
|
||||||
|
#set align(left)
|
||||||
|
#set par(first-line-indent: 0pt)
|
||||||
|
#if authors.len() == 1 {
|
||||||
|
let author = authors.at(0)
|
||||||
|
if author.gender == "m" [Виконав:\ ] else [Виконала:\ ]
|
||||||
|
[
|
||||||
|
ст. гр. #author.group\
|
||||||
|
#author.name\
|
||||||
|
]
|
||||||
|
if author.variant != none [Варіант: №#author.variant]
|
||||||
|
} else [
|
||||||
|
Виконали:\
|
||||||
|
ст. гр. #authors.at(0).group\
|
||||||
|
#authors.map(a => [ #a.name\ ])
|
||||||
|
]
|
||||||
|
|
||||||
|
#colbreak()
|
||||||
|
#set align(right)
|
||||||
|
|
||||||
|
#if mentor.gender == "m" { [Перевірив:\ ] } else { [Перевірила:\ ] }
|
||||||
|
#mentor.degree #if mentor.degree.len() >= 15 [\ ]
|
||||||
|
#mentor.name\
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
Харків -- #datetime.today().display("[year]")
|
||||||
|
]
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
|
||||||
|
heading(title)
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim:sts=2:sw=2:fdl=0:fdm=marker:cms=/*%s*/
|
7
semester-4/ОС/lb-1/src/.clangd
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
CompileFlags:
|
||||||
|
Add:
|
||||||
|
- --target=x86_64-w64-mingw32
|
||||||
|
- -I/usr/x86_64-w64-mingw32/include
|
||||||
|
- -I/usr/x86_64-w64-mingw32/include/w32api
|
||||||
|
- -DUNICODE
|
||||||
|
- -D_UNICODE
|
5
semester-4/ОС/lb-1/src/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
unicode: main.cpp
|
||||||
|
x86_64-w64-mingw32-g++ -Wall -Wextra -DUNICODE -D_UNICODE -o main.exe main.cpp
|
||||||
|
|
||||||
|
ascii: main.cpp
|
||||||
|
x86_64-w64-mingw32-g++ -Wall -Wextra -DMBCS -o main.exe main.cpp
|
4
semester-4/ОС/lb-1/src/inputA.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
test
|
||||||
|
1234
|
||||||
|
|
||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
4
semester-4/ОС/lb-1/src/inputU.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
test
|
||||||
|
1234
|
||||||
|
|
||||||
|
привіт
|
173
semester-4/ОС/lb-1/src/main.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
// #include <stringapiset.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
// #include <wchar.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
void reverse_file(const char *input_filename, const char *output_filename);
|
||||||
|
void reverse_string(char *str, size_t len, int codepage);
|
||||||
|
int get_codepage(const char *filename);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> UNICODE
|
||||||
|
// setlocale(LC_ALL, "Ukrainian");
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 1251 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> ASCII
|
||||||
|
SetConsoleOutputCP(1251);
|
||||||
|
SetConsoleCP(1251);
|
||||||
|
|
||||||
|
int tchar_size = sizeof(TCHAR);
|
||||||
|
printf("TCHAR size: %d\n", tchar_size);
|
||||||
|
|
||||||
|
char ua_strings[3][60] = {"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||||
|
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||||
|
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"};
|
||||||
|
|
||||||
|
printf("\nua_strings:\n");
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
printf("%d: %s\n", i + 1, ua_strings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nua_wstrings:\n");
|
||||||
|
wchar_t ua_wstrings[3][60] = {};
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, ua_strings[i], -1, ua_wstrings[i], 60);
|
||||||
|
|
||||||
|
printf("- - - - - - - - - - - - - - - - - - - - - -\n");
|
||||||
|
printf("%d:\n", i + 1);
|
||||||
|
|
||||||
|
_tprintf(_T("_tprintf:\t%ls\n"), ua_wstrings[i]);
|
||||||
|
std::wcout << L"std::wcout:\t" << ua_wstrings[i] << std::endl;
|
||||||
|
MessageBoxW(NULL, ua_wstrings[i], L"MessageBox", MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
wchar_t ua_wstrings_to_qsort[3][60] = {};
|
||||||
|
wchar_t *ua_wstrings_to_sort[3] = {};
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> qsort
|
||||||
|
wcscpy(ua_wstrings_to_qsort[i], ua_wstrings[i]);
|
||||||
|
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> std::sort
|
||||||
|
ua_wstrings_to_sort[i] = (wchar_t *)malloc(sizeof(wchar_t) * 60);
|
||||||
|
wcscpy(ua_wstrings_to_sort[i], ua_wstrings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nqsort:\n");
|
||||||
|
qsort(ua_wstrings_to_qsort, 3, sizeof(wchar_t) * 60,
|
||||||
|
(int (*)(const void *, const void *))wcscoll);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
_tprintf(_T("%ls\n"), ua_wstrings_to_qsort[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nstd::sort:\n");
|
||||||
|
std::sort(ua_wstrings_to_sort, ua_wstrings_to_sort + 3,
|
||||||
|
[](const wchar_t *a, const wchar_t *b) -> bool {
|
||||||
|
return wcscoll(a, b) < 0;
|
||||||
|
});
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
_tprintf(_T("%ls\n"), ua_wstrings_to_sort[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nua_strings_from_wstrings:\n");
|
||||||
|
char ua_strings_from_wstrings[3][60] = {};
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, ua_wstrings[i], -1,
|
||||||
|
ua_strings_from_wstrings[i], 60, NULL, NULL);
|
||||||
|
|
||||||
|
printf("%d: %s\n", i + 1, ua_strings_from_wstrings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nfile convertions:\n");
|
||||||
|
reverse_file("inputA.txt", "outputA.txt");
|
||||||
|
reverse_file("inputU.txt", "outputU.txt");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse_string(char *str, size_t len, int codepage) {
|
||||||
|
if (str == NULL || len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wchar_t *wstr = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
|
||||||
|
if (wstr == NULL) {
|
||||||
|
fprintf(stderr, "Error encountered while allocating memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiByteToWideChar(codepage, 0, str, len + 1, wstr, len + 1);
|
||||||
|
size_t wlen = wcslen(wstr);
|
||||||
|
|
||||||
|
for (size_t i = 0, j = wlen - 1; i < j; i++, j--) {
|
||||||
|
wchar_t temp = wstr[i];
|
||||||
|
wstr[i] = wstr[j];
|
||||||
|
wstr[j] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
WideCharToMultiByte(codepage, 0, wstr, len, str, len, NULL, NULL);
|
||||||
|
|
||||||
|
free(wstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse_file(const char *input_filename, const char *output_filename) {
|
||||||
|
FILE *input_file = fopen(input_filename, "r");
|
||||||
|
if (input_file == NULL) {
|
||||||
|
fprintf(stderr, "Cant open input file '%s'\n", input_filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *output_file = fopen(output_filename, "w");
|
||||||
|
if (output_file == NULL) {
|
||||||
|
fprintf(stderr, "Cant create output file '%s'\n", output_filename);
|
||||||
|
fclose(input_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codepage = get_codepage(input_filename);
|
||||||
|
|
||||||
|
char buffer[4096];
|
||||||
|
|
||||||
|
while (fgets(buffer, sizeof(buffer), input_file) != NULL) {
|
||||||
|
size_t len = strlen(buffer);
|
||||||
|
|
||||||
|
if (len > 0 && buffer[len - 1] == '\n') {
|
||||||
|
buffer[len - 1] = '\0';
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_string(buffer, len, codepage);
|
||||||
|
|
||||||
|
fprintf(output_file, "%s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(input_file);
|
||||||
|
fclose(output_file);
|
||||||
|
|
||||||
|
printf("Successfully reversed file '%s' to '%s'\n", input_filename,
|
||||||
|
output_filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
int get_codepage(const char *filename) {
|
||||||
|
FILE *file = fopen(filename, "r");
|
||||||
|
if (file == NULL) {
|
||||||
|
fprintf(stderr, "Cant open file '%s'\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codepage;
|
||||||
|
|
||||||
|
if (fgetc(file) == 0xEF && fgetc(file) == 0xBB && fgetc(file) == 0xBF) {
|
||||||
|
codepage = CP_UTF8;
|
||||||
|
} else {
|
||||||
|
codepage = CP_ACP;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return codepage;
|
||||||
|
}
|
4
semester-4/ОС/lb-1/src/outputA.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
tset
|
||||||
|
4321
|
||||||
|
|
||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
4
semester-4/ОС/lb-1/src/outputU.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
tset
|
||||||
|
4321
|
||||||
|
|
||||||
|
тівирп
|
357
semester-4/ОС/lb-1/Лр_1_Ситник_ПЗПІ_23_2.typ
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
#import "@local/nure:0.0.0": *
|
||||||
|
|
||||||
|
#show: lab-pz-template.with(
|
||||||
|
doctype: "ЛБ",
|
||||||
|
title: "Розробка універсальних додатків для різних типів кодувань символьної інформації",
|
||||||
|
subject_shorthand: "ОС",
|
||||||
|
department_gen: "Програмної інженерії",
|
||||||
|
authors: (
|
||||||
|
(
|
||||||
|
name: "Ситник Є. С.",
|
||||||
|
full_name_gen: "Ситника Єгора Сергійовича",
|
||||||
|
group: "ПЗПІ-23-2",
|
||||||
|
gender: "m",
|
||||||
|
variant: none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
mentor: (
|
||||||
|
name: "Мельнікова Р. В.",
|
||||||
|
gender: "f",
|
||||||
|
degree: "доц. каф. ПІ",
|
||||||
|
),
|
||||||
|
worknumber: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
#v(-spacing)
|
||||||
|
|
||||||
|
== Мета роботи
|
||||||
|
Мета даної лабораторної роботи - навчитися опрацьовувати тексти для типів кодування ASCII та UNICODE,
|
||||||
|
таким чином, щоб програма не залежала від обраного типу.
|
||||||
|
|
||||||
|
== Передмова
|
||||||
|
Я користуюсь операційною системою Arch Linux, це накладає певні обмеження, а саме:
|
||||||
|
- я не можу використовувати інтегроване середовище розробки Visual Studio, замість цього я використовую редактор NeoVim;
|
||||||
|
- я не можу використовувати компілятор MSVC, замість цього я використовую GCC та MinGW (що забезпечує кросс-компіляцію);
|
||||||
|
- код я буду запускати за допомогою шару трансляції Wine, який забезпечує сумісність з Windows.
|
||||||
|
|
||||||
|
== Хід роботи
|
||||||
|
#v(-spacing)
|
||||||
|
=== Створіть консольний застосунок для C++ програм
|
||||||
|
Створення консольного застосунку на C++ відбувається в декілька етапів:
|
||||||
|
- створення файлу "Makefile" для спрощення збірки програми;
|
||||||
|
- створення файлу "main.cpp" в якому буде знаходитись код програми.
|
||||||
|
|
||||||
|
#figure(image("img/task1/make.png"), caption: [Вміст файлу "Makefile"])
|
||||||
|
#figure(image("img/task1/main.png", width: 75%), caption: [Вміст файлу "main.cpp"])
|
||||||
|
|
||||||
|
=== Складіть оператори для програмної перевірки типу кодування, заданого за замовчуванням
|
||||||
|
Щоб дізнатись тип кодування, що задано за замовчуванням можна переглянути розмір типу "TCHAR" із заголовного файлу "tchar.h". Розмір цього типу буде дорівнювати 1 байту для ASCII та 2 байтам для UNICODE.
|
||||||
|
|
||||||
|
#figure(image("img/task2/main.png", width: 75%), caption: [Вміст файлу "main.cpp"])
|
||||||
|
#figure(image("img/task2/result.png"), caption: [Результат виконання програми])
|
||||||
|
|
||||||
|
Можемо побачити, що розмір TCHAR дорівнює 1 байту, це означає, що за замовчуванням використовується кодування ASCII.
|
||||||
|
|
||||||
|
=== Визначте тип кодування по заданих макросах в командному рядку
|
||||||
|
Оскільки під час написання команди компіляції в "Makefile" я не додав визначення макросів, які б вплинули на кодування, компілятор використовує ASCII як кодування за замовчуванням.
|
||||||
|
|
||||||
|
=== Перемикніть режим завдання символу на протилежний
|
||||||
|
Щоб задати тип кодування необхідно визначити відповідні макроси. Для UNICODE це макроси "UNICODE" (для WinAPI) та "\_UNICODE" (для стандартної бібліотеки), а для ASCII - "MBCS".
|
||||||
|
|
||||||
|
Змінимо існуючу ціль в "Makefile" щоб вона відповідала кодуванню ASCII, та додамо нову, що буде відповідати кодуванню UNICODE визначивши відповідні макроси.
|
||||||
|
|
||||||
|
#figure(image("img/task4/make.png"), caption: [Вміст файлу "Makefile"])
|
||||||
|
|
||||||
|
=== Після перемикання режиму знову перевірте тип символу за замовчуванням та командний рядок.
|
||||||
|
Перевіримо яке кодування використовує програма після проведених дій.
|
||||||
|
|
||||||
|
#figure(image("img/task5/result.png"), caption: [Результат виконання програми])
|
||||||
|
|
||||||
|
Можемо побачити, що після компіляції цілі "unicode" розмір типу "TCHAR" змінився на 2 байти, що підтверджує використання кодування UNICODE.
|
||||||
|
|
||||||
|
=== Задайте ПІБ членів своєї сім'ї в ASCII та виведіть задані значення
|
||||||
|
Щоб кириличні символи коректно друкувались в консолі необхідно виконати деякі дії, які будуть відрізнятись в залежності від кодування.
|
||||||
|
Для кодування UNICODE необхідно встановити системну локаль "Ukrainian" (або іншу, що має кириличні символи),
|
||||||
|
а для ASCII встановити кодову сторінку "CP1251".
|
||||||
|
|
||||||
|
Для встановлення системної локалі використаємо функцію "setlocale" з заголовного файлу "locale.h" який надає стандартна бібліотека,
|
||||||
|
а для встановлення кодової сторінки використаємо функції "SetConsoleOutputCP" та "SetConsoleCP" з заголовного файлу "windows.h"
|
||||||
|
який надає бібліотека WinAPI.
|
||||||
|
|
||||||
|
Також варто зазначити, що кириличні символи для ASCII відрізняються від аналогічних для UNICODE,
|
||||||
|
тому для сумісності необхідно змінити кодування файлу із UTF-8
|
||||||
|
(яке є стандартним для Unix-подібних операційних систем таких як MacOS та Linux) на CP1251.
|
||||||
|
|
||||||
|
#figure(image("img/task6/main.png"), caption: [Вміст файлу "main.cpp"])
|
||||||
|
#figure(image("img/task6/result.png"), caption: [Результат виконання програми])
|
||||||
|
|
||||||
|
=== Переведіть задані рядки в UNICODE за допомогою функції "MultiByteToWideChar"
|
||||||
|
Перевести рядок з ASCII в UNICODE можна за допомогою функції "MultiByteToWideChar" з бібліотеки WinAPI.
|
||||||
|
|
||||||
|
#figure(image("img/task7/main.png"), caption: [Код доданий до файлу "main.cpp"])
|
||||||
|
|
||||||
|
=== Виведіть отриманий масив кожним з трьох способів (функція \_tprintf, потік wcout, функція MessageBox)
|
||||||
|
|
||||||
|
#figure(image("img/task8/main.png"), caption: [Код доданий до файлу "main.cpp"])
|
||||||
|
#figure(
|
||||||
|
grid(
|
||||||
|
columns: 3,
|
||||||
|
gutter: 10pt,
|
||||||
|
align: horizon + center,
|
||||||
|
grid.cell(
|
||||||
|
colspan: 3,
|
||||||
|
image("img/task8/result.png"),
|
||||||
|
), box(image("img/task8/msg1.png")), box(image("img/task8/msg2.png")),
|
||||||
|
box(image("img/task8/msg3.png")),
|
||||||
|
),
|
||||||
|
caption: [Результат виконання програми],
|
||||||
|
)
|
||||||
|
|
||||||
|
=== Виконайте упорядкування масиву рядків, заданих в UNICODE. Для сортування використовувати універсальну стандартну функцію "qsort" та шаблонну функцію "sort"
|
||||||
|
1. Функція qsort приймає такі аргументи:
|
||||||
|
1. Вказівник на масив: Це адреса початку масиву, який потрібно відсортувати.
|
||||||
|
2. Розмір масиву: Кількість елементів у масиві, що дозволяє функції знати, скільки елементів потрібно обробити.
|
||||||
|
3. Розмір елемента масиву: Це розмір одного елемента масиву, який можна визначити, помноживши розмір типу "wchar_t" на кількість символів у рядку.
|
||||||
|
4. Вказівник на функцію порівняння: Функція, яка визначає порядок сортування. Вона повинна мати сигнатуру "int (\*)(const void\*, const void\*)". Стандартна бібліотека С має багато функцій для порівняння рядків, найпоширенішою з яких є функція "strcmp" (та її аналог "wcscmp" для "wchat_t"), однак ця функція порівнює рядки без врахування локалізації, що зіпсує результат в певних випадках. Для порівняння рядків з урахуванням локалізації можна використовувати стандартну функцію "wcscoll". Сигнатура цієї функції відрізняється від сигнатури, яку очікує "qsort", в даному випадку буде достатньо привести тип функції "wcscoll" до такого, який очікує "qsort".
|
||||||
|
|
||||||
|
2. Функція sort приймає такі аргументи:
|
||||||
|
1. Вказівник на початок масиву: Адреса першого елемента масиву, який потрібно відсортувати. Функція sort не підтримує сортування багатовимірних масивів, тому масив, який вона обробляє, повинен бути одновимірним масивом вказівників на рядки, тому перед копіюванням рядків необхідно виділити пам'ять для кожного рядка, використовуючи функцію "malloc". Зазвичай, після виділення пам'яті програміст має звільнити її, коли вона більше не потрібна. Однак, оскільки система автоматично звільняє пам'ять після завершення виконання програми, а програма для лабораторної роботи завершується дуже швидко, виклик функції "free" для звільнення виділеної пам'яті не є обов'язковим.
|
||||||
|
2. Вказівник на кінець масиву: Адреса елемента, що йде після останнього елемента масиву, що дозволяє функції визначити межі масиву.
|
||||||
|
3. Вказівник на функцію порівняння: Функція, яка визначає порядок сортування. Вона повинна мати сигнатуру "bool (\*)(wchar_t\*, wchar_t\*)". Для використання функції "wcscoll" з стандартної бібліотеки, її вихід потрібно перетворити, наприклад обгорнувши її в лямбда-функцію.
|
||||||
|
|
||||||
|
#figure(image("img/task9/strcp.png", width: 90%), caption: [Код для копіювання рядків])
|
||||||
|
#figure(image("img/task9/qsort.png", width: 90%), caption: [Код для перевірки функції "qsort"])
|
||||||
|
#figure(image("img/task9/sort.png", width: 90%), caption: [Код для перевірки функції "sort"])
|
||||||
|
#figure(image("img/task9/result.png", width: 50%), caption: [Результат виконання програми])
|
||||||
|
|
||||||
|
#let test = 2
|
||||||
|
|
||||||
|
=== Виконайте зворотне перетворення масиву з Unicode в ASCII
|
||||||
|
Перевести рядок з UNICODE в ASCII можна за допомогою функції "WideCharToMultiByte" з бібліотеки WinAPI.
|
||||||
|
|
||||||
|
#figure(image("img/task10/main.png"), caption: [Код доданий до файлу "main.cpp"])
|
||||||
|
|
||||||
|
=== Виведіть отриманий результат
|
||||||
|
|
||||||
|
#figure(image("img/task11/main.png"), caption: [Код доданий до файлу "main.cpp"])
|
||||||
|
#figure(image("img/task11/result.png", width: 80%), caption: [Результат виконання програми])
|
||||||
|
|
||||||
|
=== Задано текстовий файл. Не залежно від способу кодування символів в цьому файлі, переставити символи в кожному рядку в зворотному порядку.
|
||||||
|
|
||||||
|
#figure(image("img/task12/rfile.png"), caption: [Функція, яка створює копію файлу з розвернутими рядками])
|
||||||
|
#figure(image("img/task12/rstr.png", width: 80%), caption: [Функція, яка розвертає рядок])
|
||||||
|
#figure(image("img/task12/codepage.png", width: 80%), caption: [Функція, яка визначає кодову сторінку файлу])
|
||||||
|
|
||||||
|
#figure(image("img/task12/resultA.png"), caption: [Результат перетворення ASCII файлу])
|
||||||
|
#figure(image("img/task12/resultU.png"), caption: [Результат перетворення UNICODE файлу])
|
||||||
|
|
||||||
|
== Висновки
|
||||||
|
Під час виконання даної лабораторної роботи я навчився опрацьовувати тексти для типів кодування ASCII та UNICODE,
|
||||||
|
таким чином, щоб програма не залежала від обраного типу.
|
||||||
|
|
||||||
|
#counter(heading).update(0)
|
||||||
|
|
||||||
|
#set heading(
|
||||||
|
numbering: (i, ..nums) => {
|
||||||
|
let char = upper(ua_alpha_numbering.at(i))
|
||||||
|
if nums.pos().len() == 0 { char } else {
|
||||||
|
char + "." + nums.pos().map(str).join(".")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
#show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||||
|
linebreak()
|
||||||
|
it.body
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
= Вміст файлу "main.cpp"
|
||||||
|
```
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stringapiset.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
void reverse_file(const char *input_filename, const char *output_filename);
|
||||||
|
void reverse_string(char *str, size_t len, int codepage);
|
||||||
|
int get_codepage(const char *filename);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Зміна локалізації на українську для сумісності з UNICODE
|
||||||
|
setlocale(LC_ALL, "Ukrainian");
|
||||||
|
// Зміна кодової сторінки консолі на 1251 для сумісності з ASCII
|
||||||
|
SetConsoleOutputCP(1251);
|
||||||
|
SetConsoleCP(1251);
|
||||||
|
|
||||||
|
int tchar_size = sizeof(TCHAR);
|
||||||
|
printf("TCHAR size: %d\n", tchar_size);
|
||||||
|
|
||||||
|
char ua_strings[3][60] = {"Ситник Сергій Олексійович",
|
||||||
|
"Ситник Єгор Сергійович",
|
||||||
|
"Ситник Ольга Володимирівна"};
|
||||||
|
|
||||||
|
printf("\nua_strings:\n");
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
printf("%d: %s\n", i + 1, ua_strings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nua_wstrings:\n");
|
||||||
|
wchar_t ua_wstrings[3][60] = {};
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, ua_strings[i], -1, ua_wstrings[i], 60);
|
||||||
|
|
||||||
|
printf("- - - - - - - - - - - - - - - - - - - - - -\n");
|
||||||
|
printf("%d:\n", i + 1);
|
||||||
|
|
||||||
|
_tprintf(_T("_tprintf:\t%ls\n"), ua_wstrings[i]);
|
||||||
|
std::wcout << L"std::wcout:\t" << ua_wstrings[i] << std::endl;
|
||||||
|
// MessageBoxW(NULL, ua_wstrings[i], L"MessageBox", MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Копіювання масиву рядків для перевірки сортування
|
||||||
|
wchar_t ua_wstrings_to_qsort[3][60] = {};
|
||||||
|
wchar_t *ua_wstrings_to_sort[3] = {};
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
// Копіювання масиву для qsort
|
||||||
|
wcscpy(ua_wstrings_to_qsort[i], ua_wstrings[i]);
|
||||||
|
|
||||||
|
// Копіювання масиву для std::sort
|
||||||
|
ua_wstrings_to_sort[i] = (wchar_t *)malloc(sizeof(wchar_t) * 60);
|
||||||
|
wcscpy(ua_wstrings_to_sort[i], ua_wstrings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nqsort:\n");
|
||||||
|
qsort(ua_wstrings_to_qsort, 3, sizeof(wchar_t) * 60,
|
||||||
|
(int (*)(const void *, const void *))wcscoll);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
_tprintf(_T("%ls\n"), ua_wstrings_to_qsort[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nstd::sort:\n");
|
||||||
|
std::sort(ua_wstrings_to_sort, ua_wstrings_to_sort + 3,
|
||||||
|
[](const wchar_t *a, const wchar_t *b) -> bool {
|
||||||
|
return wcscoll(a, b) < 0;
|
||||||
|
});
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
_tprintf(_T("%ls\n"), ua_wstrings_to_sort[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nua_strings_from_wstrings:\n");
|
||||||
|
char ua_strings_from_wstrings[3][60] = {};
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, ua_wstrings[i], -1,
|
||||||
|
ua_strings_from_wstrings[i], 60, NULL, NULL);
|
||||||
|
|
||||||
|
printf("%d: %s\n", i + 1, ua_strings_from_wstrings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nfile convertions:\n");
|
||||||
|
reverse_file("inputA.txt", "outputA.txt");
|
||||||
|
reverse_file("inputU.txt", "outputU.txt");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse_string(char *str, size_t len, int codepage) {
|
||||||
|
if (str == NULL || len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wchar_t *wstr = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
|
||||||
|
if (wstr == NULL) {
|
||||||
|
fprintf(stderr, "Error encountered while allocating memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiByteToWideChar(codepage, 0, str, len + 1, wstr, len + 1);
|
||||||
|
size_t wlen = wcslen(wstr);
|
||||||
|
|
||||||
|
for (size_t i = 0, j = wlen - 1; i < j; i++, j--) {
|
||||||
|
wchar_t temp = wstr[i];
|
||||||
|
wstr[i] = wstr[j];
|
||||||
|
wstr[j] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
WideCharToMultiByte(codepage, 0, wstr, len, str, len, NULL, NULL);
|
||||||
|
|
||||||
|
free(wstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse_file(const char *input_filename, const char *output_filename) {
|
||||||
|
FILE *input_file = fopen(input_filename, "r");
|
||||||
|
if (input_file == NULL) {
|
||||||
|
fprintf(stderr, "Cant open input file '%s'\n", input_filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *output_file = fopen(output_filename, "w");
|
||||||
|
if (output_file == NULL) {
|
||||||
|
fprintf(stderr, "Cant create output file '%s'\n", output_filename);
|
||||||
|
fclose(input_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codepage = get_codepage(input_filename);
|
||||||
|
|
||||||
|
char buffer[4096];
|
||||||
|
|
||||||
|
while (fgets(buffer, sizeof(buffer), input_file) != NULL) {
|
||||||
|
size_t len = strlen(buffer);
|
||||||
|
|
||||||
|
if (len > 0 && buffer[len - 1] == '\n') {
|
||||||
|
buffer[len - 1] = '\0';
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_string(buffer, len, codepage);
|
||||||
|
|
||||||
|
fprintf(output_file, "%s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(input_file);
|
||||||
|
fclose(output_file);
|
||||||
|
|
||||||
|
printf("Successfully reversed file '%s' to '%s'\n", input_filename,
|
||||||
|
output_filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
int get_codepage(const char *filename) {
|
||||||
|
FILE *file = fopen(filename, "r");
|
||||||
|
if (file == NULL) {
|
||||||
|
fprintf(stderr, "Cant open file '%s'\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codepage;
|
||||||
|
|
||||||
|
if (fgetc(file) == 0xEF && fgetc(file) == 0xBB && fgetc(file) == 0xBF) {
|
||||||
|
codepage = CP_UTF8;
|
||||||
|
} else {
|
||||||
|
codepage = CP_ACP;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return codepage;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
= Вміст файлу "Makefile"
|
||||||
|
```
|
||||||
|
unicode: main.cpp
|
||||||
|
x86_64-w64-mingw32-g++ -Wall -Wextra -DUNICODE -D_UNICODE -o main.exe main.cpp
|
||||||
|
|
||||||
|
ascii: main.cpp
|
||||||
|
x86_64-w64-mingw32-g++ -Wall -Wextra -DMBCS -o main.exe main.cpp
|
||||||
|
```
|
2
semester-4/ОС/lb-2/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Викладач: Мельникова Р. В.
|
||||||
|
Оцінка: 96
|
BIN
semester-4/ОС/lb-2/img/crypt.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
semester-4/ОС/lb-2/img/dll_build.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
semester-4/ОС/lb-2/img/gen_pair.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
semester-4/ОС/lb-2/img/header.png
Normal file
After Width: | Height: | Size: 311 KiB |
BIN
semester-4/ОС/lb-2/img/just.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
semester-4/ОС/lb-2/img/main.png
Normal file
After Width: | Height: | Size: 786 KiB |
BIN
semester-4/ОС/lb-2/img/math.png
Normal file
After Width: | Height: | Size: 385 KiB |
692
semester-4/ОС/lb-2/lib.typ
Normal file
@ -0,0 +1,692 @@
|
|||||||
|
|
||||||
|
// Academic aliases {{{1
|
||||||
|
|
||||||
|
/// subject abbreviations to full names
|
||||||
|
#let subjects = (
|
||||||
|
"БД": "Бази даних",
|
||||||
|
"ОПНJ": "Основи програмування на Java",
|
||||||
|
"ОС": "Операційні системи",
|
||||||
|
"ПП": "Проектний практикум",
|
||||||
|
"СПМ": "Скриптові мови програмування",
|
||||||
|
"Ф": "Філософія",
|
||||||
|
)
|
||||||
|
|
||||||
|
/// education program abbreviations to name & number
|
||||||
|
#let edu_programs = (
|
||||||
|
"ПЗПІ": (
|
||||||
|
name: "Інженерія програмного забезпечення",
|
||||||
|
number: 121, // TODO: ПЗПІ is "F2" now
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Template formatting functions {{{1
|
||||||
|
|
||||||
|
/// numberless heading
|
||||||
|
#let nheading(title) = heading(depth: 1, numbering: none, title)
|
||||||
|
|
||||||
|
/// fill horizontal space with a box and not an empty space
|
||||||
|
#let hfill(width) = box(width: width, repeat(" ")) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
|
||||||
|
|
||||||
|
/// make underlined cell with filled value
|
||||||
|
#let uline(align: center, content) = underline[
|
||||||
|
#if align != left { hfill(1fr) }
|
||||||
|
#content
|
||||||
|
#if align != right { hfill(1fr) }
|
||||||
|
]
|
||||||
|
|
||||||
|
/// bold text
|
||||||
|
#let bold(content) = text(weight: "bold")[#content]
|
||||||
|
|
||||||
|
/// month name from its number
|
||||||
|
#let month_gen(month) = (
|
||||||
|
"січня",
|
||||||
|
"лютого",
|
||||||
|
"березня",
|
||||||
|
"квітня",
|
||||||
|
"травня",
|
||||||
|
"червня",
|
||||||
|
"липня",
|
||||||
|
"серпня",
|
||||||
|
"вересня",
|
||||||
|
"жовтня",
|
||||||
|
"листопада",
|
||||||
|
"грудня",
|
||||||
|
).at(month - 1)
|
||||||
|
|
||||||
|
// Helper functions {{{1
|
||||||
|
|
||||||
|
/// captioned image with label derived from path:
|
||||||
|
/// - "image.png" = @image
|
||||||
|
/// - "img/image.png" = @image
|
||||||
|
/// - "img/foo/image.png" = @foo_image
|
||||||
|
/// - "img/foo/foo_image.png" = @foo_image
|
||||||
|
/// the caption will be modified based on a conditional positional value:
|
||||||
|
/// - `none`: no change
|
||||||
|
/// - some value: "`caption` (за даними `value`)"
|
||||||
|
/// - no value: "`caption` (рисунок виконано самостійно)"
|
||||||
|
/// additional named arguments will be passed to original `image` function
|
||||||
|
#let img(path, caption, ..sink) = {
|
||||||
|
let parts = path.split(".").first().split("/")
|
||||||
|
|
||||||
|
let label_string = if parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2)) {
|
||||||
|
// ("image",), (_, "image") and (.., "img", "img_image")
|
||||||
|
parts.last()
|
||||||
|
} else {
|
||||||
|
// (.., "img", "image") = "img_image"
|
||||||
|
parts.at(-2) + "_" + parts.at(-1)
|
||||||
|
}.replace(" ", "_")
|
||||||
|
|
||||||
|
let caption = if sink.pos().len() == 0 {
|
||||||
|
caption + " (рисунок виконано самостійно)"
|
||||||
|
} else if sink.pos().first() == none {
|
||||||
|
caption
|
||||||
|
} else {
|
||||||
|
[#caption (за даними #sink.pos().first())]
|
||||||
|
}
|
||||||
|
|
||||||
|
[#figure(image(path, ..sink.named()), caption: caption) #label(label_string)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styling {{{1
|
||||||
|
/// NOTE: may be wrong
|
||||||
|
#let ua_alpha_numbering = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а"
|
||||||
|
|
||||||
|
// general outlook {{{2
|
||||||
|
// spacing between lines
|
||||||
|
#let spacing = 0.95em
|
||||||
|
|
||||||
|
#let style(it) = {
|
||||||
|
set page(
|
||||||
|
paper: "a4",
|
||||||
|
margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm),
|
||||||
|
number-align: top + right,
|
||||||
|
numbering: (..numbers) => {
|
||||||
|
if numbers.pos().at(0) != 1 {
|
||||||
|
numbering("1", numbers.pos().at(0))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
set text(font: ("Times New Roman", "Liberation Serif"), size: 14pt, hyphenate: false, lang: "uk")
|
||||||
|
set par(justify: true, first-line-indent: (amount: 1.25cm, all: true))
|
||||||
|
set underline(evade: false)
|
||||||
|
|
||||||
|
// set 1.5 line spacing
|
||||||
|
set block(spacing: spacing)
|
||||||
|
set par(spacing: spacing)
|
||||||
|
set par(leading: spacing)
|
||||||
|
|
||||||
|
// enums and lists {{{2
|
||||||
|
set enum(numbering: i => { ua_alpha_numbering.at(i) + ")" }, indent: 1.25cm, body-indent: 0.5cm)
|
||||||
|
show enum: it => {
|
||||||
|
set enum(indent: 0em, numbering: "1)")
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--])
|
||||||
|
|
||||||
|
// figures {{{2
|
||||||
|
show figure: it => {
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
it
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
set figure.caption(separator: [ -- ])
|
||||||
|
show figure.where(kind: table): set figure.caption(position: top)
|
||||||
|
show figure.caption.where(kind: table): set align(left)
|
||||||
|
|
||||||
|
// figure numbering
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
counter(math.equation).update(0)
|
||||||
|
counter(figure.where(kind: image)).update(0)
|
||||||
|
counter(figure.where(kind: table)).update(0)
|
||||||
|
counter(figure.where(kind: raw)).update(0)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
set math.equation(numbering: (..num) => numbering("(1.1)", counter(heading).get().at(0), num.pos().first()))
|
||||||
|
set figure(numbering: (..num) => numbering("1.1", counter(heading).get().at(0), num.pos().first()))
|
||||||
|
|
||||||
|
// appearance of references to images and tables {{{2
|
||||||
|
set ref(
|
||||||
|
supplement: it => {
|
||||||
|
if it == none or not it.has("kind") {
|
||||||
|
it
|
||||||
|
} else if it.kind == image {
|
||||||
|
"див. рис."
|
||||||
|
} else if it.kind == table {
|
||||||
|
"див. таблицю"
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
show ref: it => {
|
||||||
|
let el = it.element
|
||||||
|
|
||||||
|
if el == none or not el.has("kind") {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
if el.kind != image and el.kind != table {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
[(#it)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// headings {{{2
|
||||||
|
set heading(numbering: "1.1")
|
||||||
|
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "semibold")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
upper(it)
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
show heading.where(level: 2): it => {
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
block(width: 100%, spacing: 0em)[
|
||||||
|
#h(1.25cm)
|
||||||
|
#counter(heading).display(it.numbering)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 3): it => {
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
block(width: 100%, spacing: 0em)[
|
||||||
|
#h(1.25cm)
|
||||||
|
#counter(heading).display(it.numbering)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coursework template {{{1
|
||||||
|
|
||||||
|
/// DSTU 3008:2015 Template for NURE
|
||||||
|
/// -> content
|
||||||
|
/// - doc (content): Content to apply the template to.
|
||||||
|
/// - title (str): Title of the document.
|
||||||
|
/// - subject_shorthand (str): Subject short name.
|
||||||
|
/// - department_gen (str): Department name in genitive form.
|
||||||
|
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||||
|
/// - mentors ((name: str, gender: str, degree: str),): List of mentors dicts.
|
||||||
|
/// - edu_program_shorthand (str): Education program shorthand.
|
||||||
|
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
|
||||||
|
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
|
||||||
|
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
|
||||||
|
/// - bib_path path: Path to the bibliography yaml file.
|
||||||
|
/// - appendices (content): Content with appendices.
|
||||||
|
#let cw-template(
|
||||||
|
doc,
|
||||||
|
title: "NONE",
|
||||||
|
subject_shorthand: "NONE",
|
||||||
|
department_gen: "Програмної інженерії",
|
||||||
|
author: (),
|
||||||
|
mentors: (),
|
||||||
|
edu_program_shorthand: "ПЗПІ",
|
||||||
|
task_list: (),
|
||||||
|
calendar_plan: (),
|
||||||
|
abstract: (),
|
||||||
|
bib_path: "bibl.yml",
|
||||||
|
appendices: (),
|
||||||
|
) = {
|
||||||
|
set document(title: title, author: author.name)
|
||||||
|
|
||||||
|
show: style
|
||||||
|
|
||||||
|
let bib-count = state("citation-counter", ())
|
||||||
|
show cite: it => {
|
||||||
|
it
|
||||||
|
bib-count.update(((..c)) => (..c, it.key))
|
||||||
|
}
|
||||||
|
show bibliography: it => {
|
||||||
|
set text(size: 0pt)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let head_mentor = mentors.at(0)
|
||||||
|
let edu_program = edu_programs.at(edu_program_shorthand)
|
||||||
|
|
||||||
|
// page 1 {{{2
|
||||||
|
[
|
||||||
|
#set align(center)
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
|
||||||
|
|
||||||
|
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
Кафедра Програмної інженерії
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
ПОЯСНЮВАЛЬНА ЗАПИСКА
|
||||||
|
|
||||||
|
ДО КУРСОВОЇ РОБОТИ
|
||||||
|
|
||||||
|
з дисципліни: "#subjects.at(subject_shorthand, default: "NONE")"
|
||||||
|
|
||||||
|
Тема роботи: "#title"
|
||||||
|
|
||||||
|
\ \ \
|
||||||
|
|
||||||
|
#columns(2, gutter: 4cm)[
|
||||||
|
#set align(left)
|
||||||
|
|
||||||
|
#if author.gender == "m" { [Виконав\ ] } else { [Виконала\ ] } ст. гр. #author.group
|
||||||
|
|
||||||
|
\
|
||||||
|
Керівник:\
|
||||||
|
#head_mentor.degree
|
||||||
|
|
||||||
|
\
|
||||||
|
Робота захищена на оцінку
|
||||||
|
|
||||||
|
\
|
||||||
|
Комісія:\
|
||||||
|
#for mentor in mentors {
|
||||||
|
[#mentor.degree\
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#colbreak()
|
||||||
|
#set align(left)
|
||||||
|
|
||||||
|
\
|
||||||
|
#author.name
|
||||||
|
|
||||||
|
\ \
|
||||||
|
#head_mentor.name
|
||||||
|
|
||||||
|
\
|
||||||
|
#underline(" " * 35)
|
||||||
|
|
||||||
|
\ \
|
||||||
|
#for mentor in mentors {
|
||||||
|
[#mentor.name\
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
Харків -- #task_list.done_date.display("[year]")
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
]
|
||||||
|
|
||||||
|
// page 2 {{{2
|
||||||
|
{
|
||||||
|
uline[Харківський національний університет радіоелектроніки]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: (100pt, 1fr),
|
||||||
|
bold[
|
||||||
|
Кафедра
|
||||||
|
Дисципліна
|
||||||
|
Спеціальність
|
||||||
|
],
|
||||||
|
{
|
||||||
|
uline(align: left, department_gen)
|
||||||
|
linebreak()
|
||||||
|
uline(align: left, subjects.at(subject_shorthand))
|
||||||
|
linebreak()
|
||||||
|
uline(align: left, [#edu_program.number #edu_program.name])
|
||||||
|
},
|
||||||
|
)
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 1fr, 1fr),
|
||||||
|
gutter: 0.3fr,
|
||||||
|
[#bold[Курс] #uline(2)], [#bold[Група] #uline(author.group)], [#bold[Семестр] #uline(3)],
|
||||||
|
)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
uline(align: left)[_#author.full_name_gen _]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\1. Тема роботи:]
|
||||||
|
uline[#title.]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
bold[\2. Строк здачі закінченої роботи:]
|
||||||
|
uline(task_list.done_date.display("[day].[month].[year]"))
|
||||||
|
hfill(10fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\3. Вихідні дані для роботи:]
|
||||||
|
uline(task_list.source)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\4. Зміст розрахунково-пояснювальної записки:]
|
||||||
|
uline(task_list.content)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\5. Перелік графічного матеріалу:]
|
||||||
|
uline(task_list.graphics)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
bold[\6. Дата видачі завдання:]
|
||||||
|
uline(task_list.initial_date.display("[day].[month].[year]"))
|
||||||
|
hfill(10fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
// page 3 {{{2
|
||||||
|
{
|
||||||
|
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
calendar_plan.plan_table
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: (5fr, 5fr),
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 2fr, 1fr),
|
||||||
|
gutter: 0.2fr,
|
||||||
|
[
|
||||||
|
Студент \
|
||||||
|
Керівник \
|
||||||
|
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
#uline(align: center, []) \
|
||||||
|
#uline(align: center, []) \
|
||||||
|
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
|
||||||
|
],
|
||||||
|
[
|
||||||
|
\ \
|
||||||
|
#underline[#calendar_plan.approval_date.year()] р.
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
#author.name, \
|
||||||
|
#head_mentor.degree
|
||||||
|
#head_mentor.name.
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
// page 4 {{{2
|
||||||
|
[
|
||||||
|
#align(center, bold[РЕФЕРАТ]) \
|
||||||
|
|
||||||
|
#context [
|
||||||
|
#let pages = counter(page).final().at(0)
|
||||||
|
#let images = query(figure.where(kind: image)).len()
|
||||||
|
#let tables = query(figure.where(kind: table)).len()
|
||||||
|
#let bibs = bib-count.final().dedup().len()
|
||||||
|
/* TODO: why this stopped working?
|
||||||
|
#let tables = counter(figure.where(kind: table)).final().at(0)
|
||||||
|
#let images = counter(figure.where(kind: image)).final().at(0)*/
|
||||||
|
|
||||||
|
#let counters = ()
|
||||||
|
|
||||||
|
#if pages != 0 { counters.push[#pages с.] }
|
||||||
|
#if tables != 0 { counters.push[#tables табл.] }
|
||||||
|
#if images != 0 { counters.push[#images рис.] }
|
||||||
|
#if bibs != 0 { counters.push[#bibs джерел] }
|
||||||
|
|
||||||
|
Пояснювальна записка до курсової роботи: #counters.join(", ").
|
||||||
|
]
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#{
|
||||||
|
let keywords = abstract.keywords.map(upper)
|
||||||
|
let is_cyrillic = word => word.split("").any(char => ("А" <= char and char <= "я"))
|
||||||
|
|
||||||
|
let n = keywords.len()
|
||||||
|
for i in range(n) {
|
||||||
|
for j in range(0, n - i - 1) {
|
||||||
|
if (
|
||||||
|
(not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1)))
|
||||||
|
or (
|
||||||
|
is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
(keywords.at(j), keywords.at(j + 1)) = (keywords.at(j + 1), keywords.at(j))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keywords.join(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#abstract.text
|
||||||
|
]
|
||||||
|
|
||||||
|
// page 5 {{{2
|
||||||
|
outline(
|
||||||
|
title: [
|
||||||
|
ЗМІСТ
|
||||||
|
#v(spacing * 2, weak: true)
|
||||||
|
],
|
||||||
|
depth: 2,
|
||||||
|
indent: auto,
|
||||||
|
)
|
||||||
|
|
||||||
|
doc
|
||||||
|
|
||||||
|
// bibliography {{{2
|
||||||
|
{
|
||||||
|
heading(depth: 1, numbering: none)[Перелік джерел посилання]
|
||||||
|
|
||||||
|
bibliography(
|
||||||
|
bib_path,
|
||||||
|
style: "ieee",
|
||||||
|
full: true,
|
||||||
|
title: none,
|
||||||
|
)
|
||||||
|
|
||||||
|
let bib_data = yaml(bib_path)
|
||||||
|
|
||||||
|
let format-entry(citation) = {
|
||||||
|
if (citation.type == "Web") {
|
||||||
|
let date_array = citation.url.date.split("-")
|
||||||
|
let date = datetime(
|
||||||
|
year: int(date_array.at(0)),
|
||||||
|
month: int(date_array.at(1)),
|
||||||
|
day: int(date_array.at(2)),
|
||||||
|
)
|
||||||
|
[
|
||||||
|
#citation.title.
|
||||||
|
#citation.author.
|
||||||
|
URL: #citation.url.value (дата звернення: #date.display("[day].[month].[year]")).
|
||||||
|
]
|
||||||
|
} else if citation.type == "Book" [
|
||||||
|
#citation.author
|
||||||
|
#citation.title.
|
||||||
|
#citation.publisher,
|
||||||
|
#citation.date.
|
||||||
|
#citation.page-total c.
|
||||||
|
] else [
|
||||||
|
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
show enum.item: it => {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
box(width: 1.25cm)
|
||||||
|
box(width: 1em + 0.5cm)[#it.number.]
|
||||||
|
it.body
|
||||||
|
linebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
context {
|
||||||
|
for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() {
|
||||||
|
enum.item(
|
||||||
|
i + 1,
|
||||||
|
format-entry(bib_data.at(citation)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendices {{{2
|
||||||
|
{
|
||||||
|
counter(heading).update(0)
|
||||||
|
|
||||||
|
set heading(
|
||||||
|
numbering: (i, ..nums) => {
|
||||||
|
let char = upper(ua_alpha_numbering.at(i))
|
||||||
|
if nums.pos().len() == 0 { char } else {
|
||||||
|
char + "." + nums.pos().map(str).join(".")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||||
|
linebreak()
|
||||||
|
it.body
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 2): it => {
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
block(width: 100%, spacing: 0em)[
|
||||||
|
#h(1.25cm)
|
||||||
|
#counter(heading).display(it.numbering)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
appendices
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Laboratory work template {{{1
|
||||||
|
|
||||||
|
/// DSTU 3008:2015 Template for NURE
|
||||||
|
/// -> content
|
||||||
|
/// - doc (content): Content to apply the template to.
|
||||||
|
/// - doctype ("ЛБ" | "ПЗ"): Document type.
|
||||||
|
/// - title (str): Title of the document.
|
||||||
|
/// - subject_shorthand (str): Subject short name.
|
||||||
|
/// - department_gen (str): Department name in genitive form.
|
||||||
|
/// - worknumber (int): Number of the work, can be omitted.
|
||||||
|
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||||
|
/// - mentor (name: str, gender: str, degree: str): Mentors objects.
|
||||||
|
#let lab-pz-template(
|
||||||
|
doc,
|
||||||
|
doctype: "NONE",
|
||||||
|
title: "NONE",
|
||||||
|
subject_shorthand: "NONE",
|
||||||
|
department_gen: "Програмної інженерії",
|
||||||
|
worknumber: 1,
|
||||||
|
authors: (),
|
||||||
|
mentor: (),
|
||||||
|
) = {
|
||||||
|
set document(title: title, author: authors.at(0).name)
|
||||||
|
|
||||||
|
show: style
|
||||||
|
|
||||||
|
context counter(heading).update(worknumber - 1)
|
||||||
|
|
||||||
|
// page 1 {{{2
|
||||||
|
align(center)[
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
|
||||||
|
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||||
|
|
||||||
|
\ \
|
||||||
|
Кафедра #department_gen
|
||||||
|
|
||||||
|
\ \ \
|
||||||
|
Звіт \
|
||||||
|
з
|
||||||
|
#if doctype == "ЛБ" [лабораторної роботи] else [практичної роботи]
|
||||||
|
#if worknumber != none [№ #worknumber]
|
||||||
|
|
||||||
|
з дисципліни: "#subjects.at(subject_shorthand, default: "UNLNOWN SUBJECT, PLEASE OPEN AN ISSUE")"
|
||||||
|
|
||||||
|
з теми: "#title"
|
||||||
|
|
||||||
|
\ \ \ \
|
||||||
|
|
||||||
|
#columns(2)[
|
||||||
|
#set align(left)
|
||||||
|
#set par(first-line-indent: 0pt)
|
||||||
|
#if authors.len() == 1 {
|
||||||
|
let author = authors.at(0)
|
||||||
|
if author.gender == "m" [Виконав:\ ] else [Виконала:\ ]
|
||||||
|
[
|
||||||
|
ст. гр. #author.group\
|
||||||
|
#author.name\
|
||||||
|
]
|
||||||
|
if author.variant != none [Варіант: №#author.variant]
|
||||||
|
} else [
|
||||||
|
Виконали:\
|
||||||
|
ст. гр. #authors.at(0).group\
|
||||||
|
#authors.map(a => [ #a.name\ ])
|
||||||
|
]
|
||||||
|
|
||||||
|
#colbreak()
|
||||||
|
#set align(right)
|
||||||
|
|
||||||
|
#if mentor.gender == "m" { [Перевірив:\ ] } else { [Перевірила:\ ] }
|
||||||
|
#mentor.degree #if mentor.degree.len() >= 15 [\ ]
|
||||||
|
#mentor.name\
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
Харків -- #datetime.today().display("[year]")
|
||||||
|
]
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
|
||||||
|
heading(title)
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim:sts=2:sw=2:fdl=0:fdm=marker:cms=/*%s*/
|
24
semester-4/ОС/lb-2/src/.clangd
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# CompileFlags:
|
||||||
|
# Add:
|
||||||
|
# - -I/usr/x86_64-w64-mingw32/include
|
||||||
|
# - -I/usr/x86_64-w64-mingw32/include/w32api
|
||||||
|
# - -DUNICODE
|
||||||
|
# - -D_UNICODE
|
||||||
|
|
||||||
|
CompileFlags:
|
||||||
|
Add: [-Wall, -Wextra, -std=c++17, -DBUILD_SHARED, --target=x86_64-w64-mingw32]
|
||||||
|
CompilationDatabase: build/
|
||||||
|
|
||||||
|
Diagnostics:
|
||||||
|
UnusedIncludes: Strict
|
||||||
|
|
||||||
|
InlayHints:
|
||||||
|
Enabled: Yes
|
||||||
|
ParameterNames: Yes
|
||||||
|
DeducedTypes: Yes
|
||||||
|
|
||||||
|
Index:
|
||||||
|
Background: Build
|
||||||
|
|
||||||
|
Hover:
|
||||||
|
ShowAKA: Yes
|
28
semester-4/ОС/lb-2/src/Justfile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
cc := "x86_64-w64-mingw32-clang++"
|
||||||
|
flags := "-Wall -Wextra -std=c++17"
|
||||||
|
|
||||||
|
@clean:
|
||||||
|
rm -rf build
|
||||||
|
|
||||||
|
@makedir-build: clean
|
||||||
|
mkdir -p build
|
||||||
|
|
||||||
|
@build-lib-shared: makedir-build
|
||||||
|
{{cc}} {{flags}} -D BUILD_SHARED --shared -Wl,--out-implib,build/rsa.lib library/rsa.cpp -o build/rsa.dll
|
||||||
|
|
||||||
|
@build-app-shared: build-lib-shared
|
||||||
|
{{cc}} {{flags}} application/main.cpp -L build -l rsa -o build/main.exe
|
||||||
|
|
||||||
|
@build-lib-static: makedir-build
|
||||||
|
{{cc}} {{flags}} -c -D BUILD_SHARED library/rsa.cpp -o build/rsa.o
|
||||||
|
ar rcs build/rsa.lib build/rsa.o
|
||||||
|
|
||||||
|
@build-app-static: build-lib-static
|
||||||
|
{{cc}} {{flags}} -D BUILD_STATIC application/main.cpp -L build -l rsa -o build/main.exe
|
||||||
|
|
||||||
|
@run:
|
||||||
|
wine cmd /c build/main.exe
|
||||||
|
|
||||||
|
run-shared: build-app-shared run
|
||||||
|
|
||||||
|
run-static: build-app-static run
|
74
semester-4/ОС/lb-2/src/application/main.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../library/rsa.h"
|
||||||
|
|
||||||
|
char *int128_to_str(__int128_t n) {
|
||||||
|
static char str[41] = {0};
|
||||||
|
char *s = str + sizeof(str) - 1;
|
||||||
|
bool neg = n < 0;
|
||||||
|
if (neg)
|
||||||
|
n = -n;
|
||||||
|
do {
|
||||||
|
*--s = "0123456789"[n % 10];
|
||||||
|
n /= 10;
|
||||||
|
} while (n);
|
||||||
|
if (neg)
|
||||||
|
*--s = '-';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// uint64_t p0 = 8589934609, q0 = 2147483693, e0 = 65537;
|
||||||
|
// uint64_t p1 = 2147483659, q1 = 8589934621, e1 = 65537;
|
||||||
|
|
||||||
|
uint32_t p0 = 2147483659, q0 = 2147483693, e0 = 65537; // pair_0
|
||||||
|
uint32_t p1 = 2147483659, q1 = 2147483693, e1 = 65537; // pair_1
|
||||||
|
|
||||||
|
rsa_Pair pair_0 = rsa_gen_pair(p0, q0, e0);
|
||||||
|
rsa_Pair pair_1 = rsa_gen_pair(p1, q1, e1);
|
||||||
|
|
||||||
|
printf("pair_0:\n");
|
||||||
|
printf("- e:\t%s\n", int128_to_str(pair_0.e));
|
||||||
|
printf("- d:\t%s\n", int128_to_str(pair_0.d));
|
||||||
|
printf("- n:\t%s\n", int128_to_str(pair_0.n));
|
||||||
|
|
||||||
|
printf("pair_1:\n");
|
||||||
|
printf("- e:\t%s\n", int128_to_str(pair_1.e));
|
||||||
|
printf("- d:\t%s\n", int128_to_str(pair_1.d));
|
||||||
|
printf("- n:\t%s\n", int128_to_str(pair_1.n));
|
||||||
|
|
||||||
|
uint64_t t[] = {4096, 17, 8, 65500, 0x9fffffff};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 5; i++) {
|
||||||
|
printf("- - - - - - - - - - - - - - - - - -\n");
|
||||||
|
|
||||||
|
printf("t[%zu]:\t\t%lld\n", i, t[i]);
|
||||||
|
|
||||||
|
__int128_t e1t = rsa_encrypt(t[i], pair_0.e, pair_0.n);
|
||||||
|
printf("e1t:\t\t%s\n", int128_to_str(e1t));
|
||||||
|
|
||||||
|
__int128_t d1e1t = rsa_decrypt(e1t, pair_0.d, pair_0.n);
|
||||||
|
printf("d1e1t\t\t%s\n", int128_to_str(d1e1t));
|
||||||
|
|
||||||
|
if (d1e1t != t[i]) {
|
||||||
|
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||||
|
t[i], int128_to_str(d1e1t));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t e0d1e1t = rsa_encrypt(t[i], pair_1.e, pair_1.n);
|
||||||
|
printf("e0d1e1t:\t%s\n", int128_to_str(e0d1e1t));
|
||||||
|
|
||||||
|
__int128_t d0e0d1e1t = rsa_decrypt(e0d1e1t, pair_1.d, pair_1.n);
|
||||||
|
printf("d0e0d1e1t:\t%s\n", int128_to_str(d0e0d1e1t));
|
||||||
|
|
||||||
|
if (d0e0d1e1t != t[i]) {
|
||||||
|
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||||
|
t[i], int128_to_str(d0e0d1e1t));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
78
semester-4/ОС/lb-2/src/library/rsa.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "rsa.h"
|
||||||
|
|
||||||
|
__int128_t mul_mod(__int128_t a, __int128_t b, __int128_t mod) {
|
||||||
|
__int128_t res = 0;
|
||||||
|
a %= mod;
|
||||||
|
|
||||||
|
while (b > 0) {
|
||||||
|
if (b & 1)
|
||||||
|
res = (res + a) % mod;
|
||||||
|
|
||||||
|
a = (a << 1) % mod;
|
||||||
|
b >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t pow_mod(__int128_t base, __int128_t exp, __int128_t mod) {
|
||||||
|
__int128_t res = 1;
|
||||||
|
base %= mod;
|
||||||
|
|
||||||
|
while (exp > 0) {
|
||||||
|
if (exp & 1)
|
||||||
|
res = mul_mod(res, base, mod);
|
||||||
|
|
||||||
|
base = mul_mod(base, base, mod);
|
||||||
|
exp >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t mod_inverse(__int128_t e, __int128_t phi) {
|
||||||
|
__int128_t a = e, b = phi;
|
||||||
|
__int128_t x = 1, y = 0;
|
||||||
|
__int128_t x1 = 0, y1 = 1;
|
||||||
|
__int128_t q, temp;
|
||||||
|
|
||||||
|
while (b != 0) {
|
||||||
|
q = a / b;
|
||||||
|
|
||||||
|
temp = a % b;
|
||||||
|
a = b;
|
||||||
|
b = temp;
|
||||||
|
|
||||||
|
temp = x - q * x1;
|
||||||
|
x = x1;
|
||||||
|
x1 = temp;
|
||||||
|
|
||||||
|
temp = y - q * y1;
|
||||||
|
y = y1;
|
||||||
|
y1 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < 0)
|
||||||
|
x += phi;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e) {
|
||||||
|
rsa_Pair pair;
|
||||||
|
pair.e = e;
|
||||||
|
pair.n = p * q;
|
||||||
|
|
||||||
|
__int128_t phi = (p - 1) * (q - 1);
|
||||||
|
pair.d = mod_inverse(e, phi);
|
||||||
|
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n) {
|
||||||
|
return pow_mod(data, e, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n) {
|
||||||
|
return pow_mod(data, d, n);
|
||||||
|
}
|
35
semester-4/ОС/lb-2/src/library/rsa.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef RSA_LIB
|
||||||
|
#define RSA_LIB
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef BUILD_SHARED
|
||||||
|
#define BUILD_SPEC __declspec(dllexport)
|
||||||
|
#elif BUILD_STATIC
|
||||||
|
#define BUILD_SPEC
|
||||||
|
#else
|
||||||
|
#define BUILD_SPEC __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define BUILD_SPEC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
__int128_t d;
|
||||||
|
__int128_t e;
|
||||||
|
__int128_t n;
|
||||||
|
} rsa_Pair;
|
||||||
|
|
||||||
|
BUILD_SPEC rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e);
|
||||||
|
|
||||||
|
BUILD_SPEC __int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n);
|
||||||
|
BUILD_SPEC __int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
378
semester-4/ОС/lb-2/Лр_2_Ситник_ПЗПІ_23_2.typ
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
#import "@local/nure:0.0.0": *
|
||||||
|
|
||||||
|
#show: lab-pz-template.with(
|
||||||
|
doctype: "ЛБ",
|
||||||
|
title: "Створення та використання бібліотек. Частина 1",
|
||||||
|
subject_shorthand: "ОС",
|
||||||
|
department_gen: "Програмної інженерії",
|
||||||
|
authors: (
|
||||||
|
(
|
||||||
|
name: "Ситник Є. С.",
|
||||||
|
full_name_gen: "Ситника Єгора Сергійовича",
|
||||||
|
group: "ПЗПІ-23-2",
|
||||||
|
gender: "m",
|
||||||
|
variant: none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
mentor: (
|
||||||
|
name: "Мельнікова Р. В.",
|
||||||
|
gender: "f",
|
||||||
|
degree: "доц. каф. ПІ",
|
||||||
|
),
|
||||||
|
worknumber: 2,
|
||||||
|
)
|
||||||
|
|
||||||
|
#v(-spacing)
|
||||||
|
|
||||||
|
== Мета роботи
|
||||||
|
Вивчити прийоми та методи створення та використання динамічних бібліотек.
|
||||||
|
|
||||||
|
== Хід роботи
|
||||||
|
#v(-spacing)
|
||||||
|
=== Визначите необхідні функції для реалізації алгоритму RSA. Визначите серед цих функцій ті, які повинні використовуватись в зовнішніх програмах
|
||||||
|
|
||||||
|
RSA -- це криптографічний алгоритм, який використовує пару ключів: відкритий і закритий. Відкритий ключ використовується для шифрування повідомлень, а закритий -- для їх розшифрування.
|
||||||
|
|
||||||
|
Для реалізації алгоритму RSA знадобиться мінімум 3 функції:
|
||||||
|
+ функція генерації ключів;
|
||||||
|
+ функція шифрування даних;
|
||||||
|
+ функція розшифрування даних.
|
||||||
|
|
||||||
|
Також для зручності має сенс створити структуру, що буде зберігати пару ключів.
|
||||||
|
|
||||||
|
Ці функції та структура будуть доступні користувачу бібліотеки для зовнішнього використання.
|
||||||
|
|
||||||
|
=== Складіть файл заголовків таким чином, щоб цей файл заголовків можна було б використовувати для динамічної бібліотеки та програм, які використовують бібліотеку
|
||||||
|
|
||||||
|
Для операційної системи Windows створення динамічних бібліотек вимагає визначення певних розширених атрибутів класів зберігання (extended storage-class attributes), а саме -- "dllimport" та "dllexport".
|
||||||
|
|
||||||
|
Для універсальності бібліотеки необхідно створити макрос, який буде автоматично встановлювати потрібні атрибути в залежності від режиму компіляції.
|
||||||
|
|
||||||
|
Можна виділити такі особливі випадки компіляції:
|
||||||
|
+ компіляція статичної бібліотеки для операційної системи Windows;
|
||||||
|
+ компіляція динамічної бібліотеки для операційної системи Windows;
|
||||||
|
+ компіляція бібліотеки для інших операційних систем;
|
||||||
|
+ компіляція бібліотеки для використання із C;
|
||||||
|
+ компіляція бібліотеки для використання із C++.
|
||||||
|
|
||||||
|
Для визначення режиму компіляції використаємо макроси, які повинен вказати користувач, та стандартні макроси та вирази, що надає компілятор.
|
||||||
|
|
||||||
|
Також не варто забувати про можливість підключення користувачем файлу заголовків в кількох місцях. Існує кілька способів запобігання подібним ситуаціям, найкращим для цієї бібліотеки буде використання макросу, який запобігатиме повторному включенню файлу заголовків, адже цей спосіб не залежить від компілятора, що використовується.
|
||||||
|
|
||||||
|
Всі файли, що стосуються бібліотеки (файл заголовків "rsa.h" та файл реалізації "rsa.cpp") знаходитимуться в директорії "library".
|
||||||
|
|
||||||
|
#figure(image("img/header.png", width: 80%), caption: [Файл заголовків "rsa.h"])
|
||||||
|
|
||||||
|
Для запобігання повторному включенню файлу заголовків використано конструкцію із макросом "RSA_LIB". Файл буде включено тільки перший раз, всі наступні рази препроцесор не включить вміст файлу, через визначений макрос.
|
||||||
|
|
||||||
|
Для можливості використання бібліотеки як із C, так і з C++ використано конструкцію "extern C", що включається у файл тільки за умови визначення макросу "\_\_cplusplus", що додається компілятором під час компіляції в режимі C++.
|
||||||
|
|
||||||
|
Для сумісності бібліотеки із різними операційними системами використано конструкцію із макросом "\_WIN32", що визначає необхідні атрибути лише під час компіляції для цільової платформи Windows.
|
||||||
|
|
||||||
|
Для визначення атрибутів під час статичної та динамічної компіляції використано конструкцію із макросами "BUILD_SHARED" та "BUILD_STATIC".
|
||||||
|
|
||||||
|
В залежності від результату виконання вище вказаних конструкцій буде визначено макрос "BUILD_SPEC", який використовується під час оголошення функцій для додавання необхідних атрибутів.
|
||||||
|
|
||||||
|
Для всіх функцій в якості типу аргументів та результату було використано тип "\_\_int128_t", що є найбільшим із стандартних типів на момент написання. Варто зазначити, що для шифрування RSA зазвичай використовують значно більші типи, реалізовані в спеціалізованих бібліотеках, таких як "OpenSSL BN" або "GNU Multiple Precision Arithmetic Library".
|
||||||
|
|
||||||
|
Оскільки C, на відміну від C++, не має вбудованої можливості ізолювати функції та змінні в просторах імен, кожна функція та структура починаються із назви бібліотеки, а саме -- "rsa".
|
||||||
|
|
||||||
|
=== Реалізуйте функції бібліотек
|
||||||
|
|
||||||
|
Перш за все необхідно реалізувати функцію створення пари ключів на основі переданих користувачем простих чисел та відкритої експоненти @gen_pair.
|
||||||
|
|
||||||
|
#figure(image("img/gen_pair.png", width: 100%), caption: [Функція "rsa\_gen\_pair"]) <gen_pair>
|
||||||
|
|
||||||
|
Далі реалізуємо функції шифрування та розшифрування @crypt.
|
||||||
|
|
||||||
|
#figure(image("img/crypt.png", width: 100%), caption: [Функції "rsa\_encrypt" та "rsa\_decrypt"]) <crypt>
|
||||||
|
|
||||||
|
Оскільки стандартна бібліотека С не включає необхідні математичні функції їх також необхідно реалізувати @math. Ці функції розраховані на внутрішнє використання, тому їх нема в файлі заголовків.
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
image("img/math.png", width: 80%),
|
||||||
|
caption: [Математичні функції "mul\_mod", "pow\_mod" та "mod\_inverse"],
|
||||||
|
) <math>
|
||||||
|
|
||||||
|
=== Створіть динамічну бібліотеку
|
||||||
|
|
||||||
|
Оскільки я використовую операційну систему Arch Linux, у мене нема доступу до компілятора Microsoft MSVC. Натомість мною було використано компілятор Clang із проєкту LLVM, та набір інструментів MinGW, що забезпечують кросс-компіляцію для Windows на POSIX-сумісних операційних системах (Linux, MacOS, BSD і подібних).
|
||||||
|
|
||||||
|
Під час компіляції динамічної бібліотеки необхідно:
|
||||||
|
+ визначити макрос "BUILD_SHARED";
|
||||||
|
+ вказати прапорець "shared" для компілятора;
|
||||||
|
+ встановити значення, що відповідає назві бібліотеки, для прапорця "out-implib" для компонувальника.
|
||||||
|
|
||||||
|
Компілятор автоматично викликає компонувальник, передати аргументи для нього можна за допомогою прапорця "Wl".
|
||||||
|
|
||||||
|
Динамічні бібліотеки для Windows складаються з 2 компонентів:
|
||||||
|
+ файл із розширенням ".dll" в якому знаходиться реалізація бібліотеки;
|
||||||
|
+ файл із розширенням ".lib" в якому знаходиться інформація, необхідна для зв'язування програми та бібліотеки.
|
||||||
|
|
||||||
|
Для зручнішого управління проєктом має сенс використовувати систему збірки, та визначати всі команди компіляції за її допомогою. Я використаю систему збірки "Just" @just. Всі скомпільовані файли будуть знаходитись в директорії "build".
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
image("img/just.png", width: 100%),
|
||||||
|
caption: [Вміст "Justfile" з інструкціями для збірки],
|
||||||
|
) <just>
|
||||||
|
|
||||||
|
Скомпілюємо бібліотеку та перевіримо результат @dll_build.
|
||||||
|
#figure(
|
||||||
|
image("img/dll_build.png", width: 100%),
|
||||||
|
caption: [Результат збірки динамічної бібліотеки],
|
||||||
|
) <dll_build>
|
||||||
|
|
||||||
|
|
||||||
|
Можемо побачити, що компіляція пройшла без помилок та попереджень, та після компіляції, як і очікувалося, ми отримали 2 файли бібліотеки.
|
||||||
|
|
||||||
|
=== Реалізуйте головну програму для динамічної бібліотеки для першого способу її використання
|
||||||
|
|
||||||
|
Відповідно умові реалізуємо програму із використанням функцій бібліотеки. Для доступу до них необхідно підключити файл заголовків бібліотеки.
|
||||||
|
|
||||||
|
Оберемо пари простих чисел та відкриті експоненти для створення 2 пар ключів, створимо пари, почергово перевіримо роботу функцій шифрування та дешифрування із 2 парами ключів на різних даних друкуючу в консоль результат кожного етапу.
|
||||||
|
|
||||||
|
Оскільки бібліотека розрахована на роботу із даними типу "\_\_int128_t", а стандартні функції друку в консоль не підтримують цей тип, додатково реалізуємо функцію для перетворення чисел такого типу на строки.
|
||||||
|
|
||||||
|
Всі файли, що стосуються програми (файл реалізації "main.cpp") знаходитимуться в директорії "application".
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
image("img/main.png", width: 70%),
|
||||||
|
caption: [Вміст файлу "main.cpp"],
|
||||||
|
) <main>
|
||||||
|
|
||||||
|
== Висновки
|
||||||
|
Під час виконання даної лабораторної роботи я вивчив прийоми та методи створення та використання динамічних бібліотек.
|
||||||
|
|
||||||
|
#counter(heading).update(0)
|
||||||
|
|
||||||
|
#set heading(
|
||||||
|
numbering: (i, ..nums) => {
|
||||||
|
let char = upper(ua_alpha_numbering.at(i))
|
||||||
|
if nums.pos().len() == 0 { char } else {
|
||||||
|
char + "." + nums.pos().map(str).join(".")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
#show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||||
|
linebreak()
|
||||||
|
it.body
|
||||||
|
v(spacing * 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
= Вміст файлу "rsa.h"
|
||||||
|
```
|
||||||
|
#ifndef RSA_LIB
|
||||||
|
#define RSA_LIB
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef BUILD_SHARED
|
||||||
|
#define BUILD_SPEC __declspec(dllexport)
|
||||||
|
#elif BUILD_STATIC
|
||||||
|
#define BUILD_SPEC
|
||||||
|
#else
|
||||||
|
#define BUILD_SPEC __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define BUILD_SPEC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
__int128_t d;
|
||||||
|
__int128_t e;
|
||||||
|
__int128_t n;
|
||||||
|
} rsa_Pair;
|
||||||
|
|
||||||
|
BUILD_SPEC rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e);
|
||||||
|
|
||||||
|
BUILD_SPEC __int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n);
|
||||||
|
BUILD_SPEC __int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
= Вміст файлу "rsa.cpp"
|
||||||
|
```
|
||||||
|
#include "rsa.h"
|
||||||
|
|
||||||
|
__int128_t mul_mod(__int128_t a, __int128_t b, __int128_t mod) {
|
||||||
|
__int128_t res = 0;
|
||||||
|
a %= mod;
|
||||||
|
|
||||||
|
while (b > 0) {
|
||||||
|
if (b & 1)
|
||||||
|
res = (res + a) % mod;
|
||||||
|
|
||||||
|
a = (a << 1) % mod;
|
||||||
|
b >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t pow_mod(__int128_t base, __int128_t exp, __int128_t mod) {
|
||||||
|
__int128_t res = 1;
|
||||||
|
base %= mod;
|
||||||
|
|
||||||
|
while (exp > 0) {
|
||||||
|
if (exp & 1)
|
||||||
|
res = mul_mod(res, base, mod);
|
||||||
|
|
||||||
|
base = mul_mod(base, base, mod);
|
||||||
|
exp >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t mod_inverse(__int128_t e, __int128_t phi) {
|
||||||
|
__int128_t a = e, b = phi;
|
||||||
|
__int128_t x = 1, y = 0;
|
||||||
|
__int128_t x1 = 0, y1 = 1;
|
||||||
|
__int128_t q, temp;
|
||||||
|
|
||||||
|
while (b != 0) {
|
||||||
|
q = a / b;
|
||||||
|
|
||||||
|
temp = a % b;
|
||||||
|
a = b;
|
||||||
|
b = temp;
|
||||||
|
|
||||||
|
temp = x - q * x1;
|
||||||
|
x = x1;
|
||||||
|
x1 = temp;
|
||||||
|
|
||||||
|
temp = y - q * y1;
|
||||||
|
y = y1;
|
||||||
|
y1 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < 0)
|
||||||
|
x += phi;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsa_Pair rsa_gen_pair(__int128_t p, __int128_t q, __int128_t e) {
|
||||||
|
rsa_Pair pair;
|
||||||
|
pair.e = e;
|
||||||
|
pair.n = p * q;
|
||||||
|
|
||||||
|
__int128_t phi = (p - 1) * (q - 1);
|
||||||
|
pair.d = mod_inverse(e, phi);
|
||||||
|
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t rsa_encrypt(__int128_t data, __int128_t e, __int128_t n) {
|
||||||
|
return pow_mod(data, e, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t rsa_decrypt(__int128_t data, __int128_t d, __int128_t n) {
|
||||||
|
return pow_mod(data, d, n);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
= Вміст файлу "main.cpp"
|
||||||
|
```
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../library/rsa.h"
|
||||||
|
|
||||||
|
char *int128_to_str(__int128_t n) {
|
||||||
|
static char str[41] = {0};
|
||||||
|
char *s = str + sizeof(str) - 1;
|
||||||
|
bool neg = n < 0;
|
||||||
|
if (neg)
|
||||||
|
n = -n;
|
||||||
|
do {
|
||||||
|
*--s = "0123456789"[n % 10];
|
||||||
|
n /= 10;
|
||||||
|
} while (n);
|
||||||
|
if (neg)
|
||||||
|
*--s = '-';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
uint64_t p0 = 8589934609, q0 = 2147483693, e0 = 65537;
|
||||||
|
uint64_t p1 = 2147483659, q1 = 8589934621, e1 = 65537;
|
||||||
|
|
||||||
|
rsa_Pair pair_0 = rsa_gen_pair(p0, q0, e0);
|
||||||
|
rsa_Pair pair_1 = rsa_gen_pair(p1, q1, e1);
|
||||||
|
|
||||||
|
printf("pair_0:\n");
|
||||||
|
printf("- e:\t%s\n", int128_to_str(pair_0.e));
|
||||||
|
printf("- d:\t%s\n", int128_to_str(pair_0.d));
|
||||||
|
printf("- n:\t%s\n", int128_to_str(pair_0.n));
|
||||||
|
|
||||||
|
printf("pair_1:\n");
|
||||||
|
printf("- e:\t%s\n", int128_to_str(pair_1.e));
|
||||||
|
printf("- d:\t%s\n", int128_to_str(pair_1.d));
|
||||||
|
printf("- n:\t%s\n", int128_to_str(pair_1.n));
|
||||||
|
|
||||||
|
uint64_t t[] = {22, 17, 2, 65500, 100};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 5; i++) {
|
||||||
|
printf("- - - - - - - - - - - - - - - - - -\n");
|
||||||
|
|
||||||
|
printf("t[%zu]:\t\t%lld\n", i, t[i]);
|
||||||
|
|
||||||
|
__int128_t e1t = rsa_encrypt(t[i], pair_0.e, pair_0.n);
|
||||||
|
printf("e1t:\t\t%s\n", int128_to_str(e1t));
|
||||||
|
|
||||||
|
__int128_t d1e1t = rsa_decrypt(e1t, pair_0.d, pair_0.n);
|
||||||
|
printf("d1e1t:\t\t%s\n", int128_to_str(d1e1t));
|
||||||
|
|
||||||
|
if (d1e1t != t[i]) {
|
||||||
|
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||||
|
t[i], int128_to_str(d1e1t));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int128_t e0d1e1t = rsa_encrypt(t[i], pair_1.e, pair_1.n);
|
||||||
|
printf("e0d1e1t:\t%s\n", int128_to_str(e0d1e1t));
|
||||||
|
|
||||||
|
__int128_t d0e0d1e1t = rsa_decrypt(e0d1e1t, pair_1.d, pair_1.n);
|
||||||
|
printf("d0e0d1e1t:\t%s\n", int128_to_str(d0e0d1e1t));
|
||||||
|
|
||||||
|
if (d0e0d1e1t != t[i]) {
|
||||||
|
fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
|
||||||
|
t[i], int128_to_str(d0e0d1e1t));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
= Вміст файлу "Justfile"
|
||||||
|
```
|
||||||
|
cc := "x86_64-w64-mingw32-clang++"
|
||||||
|
flags := "-Wall -Wextra -std=c++17"
|
||||||
|
|
||||||
|
@clean:
|
||||||
|
rm -rf build
|
||||||
|
|
||||||
|
@makedir-build: clean
|
||||||
|
mkdir -p build
|
||||||
|
|
||||||
|
@build-lib-shared: makedir-build
|
||||||
|
{{cc}} {{flags}} -D BUILD_SHARED --shared -Wl,--out-implib,build/rsa.lib library/rsa.cpp -o build/rsa.dll
|
||||||
|
|
||||||
|
@build-app-shared: build-lib-shared
|
||||||
|
{{cc}} {{flags}} application/main.cpp -L build -l rsa -o build/main.exe
|
||||||
|
```
|
2
semester-4/ОС/lb-3/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Викладач: Мельникова Р. В.
|
||||||
|
Оцінка: 96
|
BIN
semester-4/ОС/lb-3/img/1/check.png
Normal file
After Width: | Height: | Size: 219 KiB |
BIN
semester-4/ОС/lb-3/img/1/def.png
Normal file
After Width: | Height: | Size: 25 KiB |