@@ -24,7 +24,7 @@ document.addEventListener('DOMContentLoaded', () => {
2424
2525 const themeSwitcher = document . querySelectorAll ( '#theme' )
2626
27- themeSwitcher . forEach ( ( element ) => {
27+ themeSwitcher . forEach ( element => {
2828 element . addEventListener ( 'click' , ( ) => {
2929 document . body . classList . toggle ( 'dark' )
3030 localStorage . setItem (
@@ -48,198 +48,165 @@ class Vector {
4848 this . vector = generateVector ( vectorLength )
4949 this . M = isMonotone ( this . vector )
5050 this . L = isLinear ( this . vector )
51- this . T0 = this . vector . join ( '' ) [ 0 ] == '0' ? true : false
52- this . T1 = this . vector . join ( '' ) [ this . vector . length - 1 ] == '1' ? true : false
53- this . S = true
54- for ( let i = 0 ; i < this . vector . length / 2 ; i ++ ) {
55- if ( this . vector [ i ] == this . vector [ this . vector . length - 1 - i ] ) {
56- this . S = false
57- break
58- }
59- }
51+ this . T0 = this . vector [ 0 ] === 0
52+ this . T1 = this . vector [ this . vector . length - 1 ] === 1
53+ this . S = isSelfDual ( this . vector )
6054 }
55+
6156 getVector ( ) {
6257 return this . vector
6358 }
59+
6460 toString ( ) {
6561 return this . vector . join ( '' )
6662 }
63+
6764 isCanceled ( ) {
68- const notCanceled = [ ]
69- if ( ! this . M ) notCanceled . push ( 'M' )
70- if ( ! this . L ) notCanceled . push ( 'L' )
71- if ( ! this . T0 ) notCanceled . push ( 'T0' )
72- if ( ! this . T1 ) notCanceled . push ( 'T1' )
73- if ( ! this . S ) notCanceled . push ( 'S' )
74- return notCanceled
65+ const canceledClasses = [ ]
66+ if ( this . M ) canceledClasses . push ( 'M' )
67+ if ( this . L ) canceledClasses . push ( 'L' )
68+ if ( this . T0 ) canceledClasses . push ( 'T0' )
69+ if ( this . T1 ) canceledClasses . push ( 'T1' )
70+ if ( this . S ) canceledClasses . push ( 'S' )
71+ return canceledClasses
7572 }
7673}
7774
7875let selectedClasses = [ ]
79- let zhegalkinLength //для рекурсии
80- let classes
81- let vector
76+ let currentVector = null
77+ let canceledClasses
78+
79+ // Блокируем кнопки при загрузке
80+ classButtons . forEach ( btn => ( btn . style . pointerEvents = 'none' ) )
81+ checkResultButton . disabled = true
8282
83+ // Обработчики для кнопок классов
8384classButtons . forEach ( button => {
84- //проверка выбран ли класс
8585 button . addEventListener ( 'click' , ( ) => {
86+ if ( ! currentVector ) {
87+ notyf . error ( 'Сначала сгенерируйте вектор!' )
88+ return
89+ }
90+
91+ button . classList . toggle ( 'selected' )
8692 if ( button . classList . contains ( 'selected' ) ) {
87- button . classList . remove ( 'selected' )
88- selectedClasses = selectedClasses . filter ( cls => cls !== button . id )
89- } else {
90- button . classList . add ( 'selected' )
9193 selectedClasses . push ( button . id )
94+ } else {
95+ selectedClasses = selectedClasses . filter ( cls => cls !== button . id )
9296 }
9397 } )
9498} )
9599
100+ // Генерация вектора
96101generateVectorButton . addEventListener ( 'click' , ( ) => {
97- document
98- . querySelectorAll ( '.class-button' )
99- . forEach ( btn => ( btn . style . pointerEvents = 'all' ) )
100- checkResultButton . disabled = false
101-
102- const power = Math . floor ( Math . random ( ) * 2 ) + 2
102+ const power = Math . floor ( Math . random ( ) * 2 ) + 2 // 2 или 3 переменные
103103 const vectorLength = Math . pow ( 2 , power )
104- vector = new Vector ( vectorLength )
105- if ( ! vector . isCanceled ( ) ) {
106- while ( ! vector . isCanceled ( ) ) {
107- const power = Math . floor ( Math . random ( ) * 2 ) + 2
108- const vectorLength = Math . pow ( 2 , power )
109- vector = new Vector ( vectorLength )
110- }
111- }
112- console . log ( vector . isCanceled ( ) )
113-
114- outputContainer . innerText = `Вектор: {${ vector } }`
115-
116- // Очистить все дополнительные классы и выделения
117- classButtons . forEach ( button => {
118- button . classList . remove (
119- 'selected' ,
120- 'right' ,
121- 'wrong' ,
122- 'wrong-unselected' ,
123- 'right-unselected'
124- )
104+ currentVector = new Vector ( vectorLength )
105+ canceledClasses = currentVector . isCanceled ( )
106+ canceledClasses . length === 0 ? generateVectorButton . click ( ) : null
107+
108+ outputContainer . textContent = `Вектор: ${ currentVector } `
109+
110+ // Разблокируем кнопки
111+ classButtons . forEach ( btn => {
112+ btn . style . pointerEvents = 'auto'
113+ btn . classList . remove ( 'selected' , 'right' , 'wrong' , 'wrong-unselected' )
125114 } )
115+ checkResultButton . disabled = false
126116 selectedClasses = [ ]
127117} )
128118
119+ // Проверка результата
129120checkResultButton . addEventListener ( 'click' , ( ) => {
130- checkResultButton . disabled = true
131- classes = [ ] //классы в которых не содержится набор
132- const allClasses = [ 'M' , 'L' , 'T0' , 'T1' , 'S' ]
121+ if ( ! currentVector ) {
122+ notyf . error ( 'Сначала сгенерируйте вектор!' )
123+ return
124+ }
133125
134- const canceled = vector . isCanceled ( ) //классы которым не принадлежит вектор
135- allClasses . forEach ( cls => {
136- if ( canceled . includes ( cls ) && ! classes . includes ( cls ) ) {
137- classes . push ( cls )
138- }
139- } )
126+ let allCorrect = true
140127
141- let flag = false
142- selectedClasses . forEach ( clas => {
143- if ( classes . includes ( clas ) ) {
144- flag = true
145- document
146- . querySelector ( `div #${ clas } ` )
147- . classList . remove ( 'selected' , 'right' )
148- document . querySelector ( `div #${ clas } ` ) . classList . add ( 'wrong' )
128+ // Проверяем выбранные классы
129+ selectedClasses . forEach ( cls => {
130+ const button = document . getElementById ( cls )
131+ if ( canceledClasses . includes ( cls ) ) {
132+ button . classList . add ( 'right' )
149133 } else {
150- document
151- . querySelector ( `div #${ clas } ` )
152- . classList . remove ( 'selected' , 'wrong' )
153- document . querySelector ( `div #${ clas } ` ) . classList . add ( 'right' )
134+ button . classList . add ( 'wrong' )
135+ allCorrect = false
154136 }
155137 } )
156138
157- classButtons . forEach ( button => {
158- if ( selectedClasses . includes ( button . id ) && classes . includes ( button . id ) ) {
159- flag = true
160- button . classList . remove ( 'wrong' , 'right' , 'selected' )
161- button . classList . add ( 'wrong-unselected' )
162- } else if (
163- ! selectedClasses . includes ( button . id ) &&
164- classes . includes ( button . id )
165- ) {
166- button . classList . remove ( 'wrong' , 'right' , 'selected' )
167- button . classList . add ( 'right-unselected' )
139+ // Помечаем пропущенные классы
140+ canceledClasses . forEach ( cls => {
141+ if ( ! selectedClasses . includes ( cls ) ) {
142+ document . getElementById ( cls ) . classList . add ( 'wrong-unselected' )
143+ allCorrect = false
168144 }
169145 } )
170146
171- flag ? notyf . error ( 'Ошибка!' ) : notyf . success ( 'Все правильно!' )
172-
173- document
174- . querySelectorAll ( '.class-button' )
175- . forEach ( btn => ( btn . style . pointerEvents = 'none' ) )
147+ // Выводим результат
148+ if ( allCorrect && selectedClasses . length === canceledClasses . length ) {
149+ notyf . success ( 'Все правильно!' )
150+ } else {
151+ notyf . error ( 'Есть ошибки в выборе классов' )
152+ }
176153
177- console . log ( classes , selectedClasses )
154+ // Блокируем кнопки после проверки
155+ classButtons . forEach ( btn => ( btn . style . pointerEvents = 'none' ) )
156+ checkResultButton . disabled = true
178157} )
179158
159+ // Вспомогательные функции
180160function generateVector ( length ) {
181- const vector = [ ]
182- for ( let i = 0 ; i < length ; i ++ ) {
183- vector . push ( Math . random ( ) < 0.5 ? 0 : 1 )
184- }
185- return vector
186- }
187-
188- function getBinaryRepresentation ( vector ) {
189- const binaryVector = [ ]
190- for ( let i = 0 ; i < vector . length ; i ++ ) {
191- const binaryRepresentation = i
192- . toString ( 2 )
193- . padStart ( Math . log2 ( vector . length ) , '0' )
194- binaryVector [ i ] = binaryRepresentation
195- }
196- return binaryVector
161+ return Array . from ( { length } , ( ) => ( Math . random ( ) < 0.5 ? 0 : 1 ) )
197162}
198163
199164function isMonotone ( vector ) {
200- const binaryVector = getBinaryRepresentation ( vector )
165+ const n = Math . log2 ( vector . length )
166+ if ( ! Number . isInteger ( n ) ) return false
201167
202168 for ( let i = 0 ; i < vector . length ; i ++ ) {
203169 for ( let j = i + 1 ; j < vector . length ; j ++ ) {
204- const binaryRepresentationI = binaryVector [ i ]
205- const binaryRepresentationJ = binaryVector [ j ]
206- const countOnesI = binaryRepresentationI . split ( '1' ) . length - 1
207- const countOnesJ = binaryRepresentationJ . split ( '1' ) . length - 1
208-
209- if ( countOnesI < countOnesJ && vector [ i ] === 0 && vector [ j ] === 1 ) {
210- return false
170+ let covers = true
171+ for ( let k = 0 ; k < n ; k ++ ) {
172+ if ( ( ( i >> k ) & 1 ) > ( ( j >> k ) & 1 ) ) {
173+ covers = false
174+ break
175+ }
211176 }
177+ if ( covers && vector [ i ] > vector [ j ] ) return false
212178 }
213179 }
214-
215180 return true
216181}
217182
218183function isLinear ( vector ) {
219- let linear = true
220- zhegalkinLength = vector . length
221- const zhegalkinPolynom = createZhegalkin ( vector , [ ] , vector )
222- const binaryZhegalkin = getBinaryRepresentation ( zhegalkinPolynom )
223- for ( let i = 0 ; i < binaryZhegalkin . length ; i ++ ) {
224- if ( binaryZhegalkin [ i ] . split ( 1 ) . length > 1 && zhegalkinPolynom [ i ] === 1 ) {
225- linear = false
226- break
184+ const n = Math . log2 ( vector . length )
185+ if ( ! Number . isInteger ( n ) ) return false
186+
187+ const coeffs = [ ...vector ]
188+ for ( let i = 0 ; i < vector . length ; i ++ ) {
189+ for ( let j = 0 ; j < i ; j ++ ) {
190+ if ( ( i & j ) === j ) {
191+ coeffs [ i ] ^= coeffs [ j ]
192+ }
227193 }
228194 }
229- return linear
195+
196+ for ( let i = 0 ; i < vector . length ; i ++ ) {
197+ if ( coeffs [ i ] && i . toString ( 2 ) . split ( '1' ) . length - 1 > 1 ) {
198+ return false
199+ }
200+ }
201+ return true
230202}
231203
232- function createZhegalkin ( vector , polynom ) {
233- if ( polynom . length < zhegalkinLength - 1 ) {
234- let polynomialRepresentation = [ ]
235- for ( let i = 1 ; i < vector . length ; i ++ ) {
236- polynomialRepresentation . push ( vector [ i ] ^ vector [ i - 1 ] )
204+ function isSelfDual ( vector ) {
205+ if ( vector . length % 2 !== 0 ) return false
206+ for ( let i = 0 ; i < vector . length / 2 ; i ++ ) {
207+ if ( vector [ i ] === vector [ vector . length - 1 - i ] ) {
208+ return false
237209 }
238- polynom . push ( polynomialRepresentation [ 0 ] )
239- vector = polynomialRepresentation
240- createZhegalkin ( vector , polynom )
241- } else {
242- polynom . push ( vector [ 0 ] )
243210 }
244- return polynom
211+ return true
245212}
0 commit comments