Compare commits
11 Commits
6d56eb5c8a
...
37314cf9db
| Author | SHA1 | Date | |
|---|---|---|---|
|
37314cf9db
|
|||
|
e6ec271afd
|
|||
|
0e46e1a292
|
|||
|
11c90daaa2
|
|||
|
a280dfd564
|
|||
|
9d6b1f767e
|
|||
|
7141534e9f
|
|||
|
8e9567e1a2
|
|||
|
124b4c7a33
|
|||
|
5afec8149d
|
|||
|
38c3be5740
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
/out/
|
||||
# ---> Scala
|
||||
*.class
|
||||
*.log
|
||||
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
6
.idea/misc.xml
generated
Normal file
6
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Lab17.iml" filepath="$PROJECT_DIR$/Lab17.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
13
Lab17.iml
Normal file
13
Lab17.iml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="scala-sdk-2.13.12" level="project" />
|
||||
<orderEntry type="library" name="FunGraphics-1.5.13" level="application" />
|
||||
</component>
|
||||
</module>
|
||||
32
src/Hanoi.scala
Normal file
32
src/Hanoi.scala
Normal file
@@ -0,0 +1,32 @@
|
||||
import scala.collection.mutable
|
||||
|
||||
class Hanoi(val n: Int, val left: Char, val mid: Char, val right: Char) {
|
||||
val lists: mutable.HashMap[Char, mutable.Stack[Int]] = new mutable.HashMap()
|
||||
lists(left) = mutable.Stack.range(1, n + 1)
|
||||
lists(mid) = mutable.Stack.empty
|
||||
lists(right) = mutable.Stack.empty
|
||||
|
||||
def move(from: Char, to: Char): Unit = {
|
||||
val i: Int = lists(from).pop()
|
||||
println(s"Moving disk $i from $from->$to")
|
||||
lists(to).push(i)
|
||||
}
|
||||
|
||||
def solve(): Unit = {
|
||||
hanoi(n, left, mid, right)
|
||||
}
|
||||
|
||||
private def hanoi(n: Int, start: Char, aux: Char, end: Char): Unit = {
|
||||
if (n == 0) return
|
||||
hanoi(n - 1, start, end, aux)
|
||||
move(start, end)
|
||||
hanoi(n - 1, aux, start, end)
|
||||
}
|
||||
}
|
||||
|
||||
object Hanoi {
|
||||
def main(args: Array[String]): Unit = {
|
||||
val hanoi: Hanoi = new Hanoi(3, 'A', 'B', 'C')
|
||||
hanoi.solve()
|
||||
}
|
||||
}
|
||||
93
src/logo/NaturalTree.scala
Normal file
93
src/logo/NaturalTree.scala
Normal file
@@ -0,0 +1,93 @@
|
||||
package logo
|
||||
|
||||
import java.awt.{Color, Point}
|
||||
import scala.util.Random
|
||||
|
||||
class NaturalTree(width: Int, height: Int, angleStep_ : Double) extends Tree(width, height, angleStep_) {
|
||||
val MIN_STRAW_ANGLE: Double = 60
|
||||
val MAX_STRAW_ANGLE: Double = 100
|
||||
val MIN_N_STRAWS: Int = 90
|
||||
val MAX_N_STRAWS: Int = 200
|
||||
//val STRAW_COLOR1: Color = new Color(230, 188, 43)
|
||||
//val STRAW_COLOR2: Color = new Color(255, 226, 71)
|
||||
//val STRAW_COLOR1: Color = new Color(96, 163, 67)
|
||||
//val STRAW_COLOR2: Color = new Color(112, 198, 76)
|
||||
val STRAW_COLOR1: Color = new Color(108, 83, 61)
|
||||
val STRAW_COLOR2: Color = new Color(174, 105, 44)
|
||||
val TRUNK_COLOR: Color = new Color(65, 61, 64)
|
||||
|
||||
override def drawTree(n: Int, length: Double): Unit = {
|
||||
var n2: Int = n
|
||||
val r: Double = math.random()
|
||||
if (r < 0.25) {
|
||||
n2 -= 1
|
||||
} else if (r > 0.9) {
|
||||
if (n2 < 2) {
|
||||
n2 += 3
|
||||
}
|
||||
}
|
||||
turn(angleStep * (math.random() - 0.5) * 2)
|
||||
val a: Double = angleStep
|
||||
angleStep -= math.random() * angleStep / 10
|
||||
super.drawTree(n2, length)
|
||||
angleStep = a
|
||||
}
|
||||
|
||||
override def drawBranch(length: Double): Unit = {
|
||||
setPenWidth((length / 10).toFloat)
|
||||
setColor(TRUNK_COLOR)
|
||||
super.drawBranch(length)
|
||||
}
|
||||
|
||||
override def drawLeaf(length: Double): Unit = {
|
||||
val angle: Double = getTurtleAngle()
|
||||
val pos: Point = getPosition()
|
||||
val nStraws: Int = Random.between(MIN_N_STRAWS, MAX_N_STRAWS)
|
||||
val strawsAngle: Double = Random.between(MIN_STRAW_ANGLE, MAX_STRAW_ANGLE)
|
||||
val step: Double = strawsAngle / (nStraws - 1)
|
||||
val oAngle: Double = angle - strawsAngle / 2
|
||||
val strawLen: Double = length * 20
|
||||
|
||||
setPenWidth(1f)
|
||||
for (i: Int <- 0 until nStraws) {
|
||||
setPenWidth(0.5f + (nStraws - i) / (nStraws - 1f) / 10)
|
||||
setColor(lerpCol((nStraws - i) / (nStraws - 1.0)))
|
||||
//val a: Double = oAngle + i * step + (math.random() * 2 -1) * step / 5
|
||||
val a: Double = oAngle + math.random() * strawsAngle
|
||||
var l: Double = strawLen * (nStraws.toDouble - i) / nStraws
|
||||
l += (math.random() * 2 - 1) * l / 2
|
||||
setAngle(a)
|
||||
jump(pos.x, pos.y)
|
||||
//forward(strawLen + (math.random() * 2 - 1) * strawLen / 2)
|
||||
forward(l)
|
||||
}
|
||||
jump(pos.x, pos.y)
|
||||
setAngle(angle)
|
||||
}
|
||||
|
||||
def lerpCol(f: Double): Color = {
|
||||
val r: Int = ((STRAW_COLOR2.getRed - STRAW_COLOR1.getRed) * f + STRAW_COLOR1.getRed).toInt
|
||||
val g: Int = ((STRAW_COLOR2.getGreen - STRAW_COLOR1.getGreen) * f + STRAW_COLOR1.getGreen).toInt
|
||||
val b: Int = ((STRAW_COLOR2.getBlue - STRAW_COLOR1.getBlue) * f + STRAW_COLOR1.getBlue).toInt
|
||||
return new Color(
|
||||
math.min(255, math.max(0, r)),
|
||||
math.min(255, math.max(0, g)),
|
||||
math.min(255, math.max(0, b))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object NaturalTree {
|
||||
def main(args: Array[String]): Unit = {
|
||||
val tree: NaturalTree = new NaturalTree(600, 600, 25)
|
||||
tree.jump(300, 600)
|
||||
tree.setAngle(-90)
|
||||
tree.drawTree(8, 80)
|
||||
|
||||
for (i: Int <- 0 until 10) {
|
||||
tree.jump(Random.between(0, 600), 600)
|
||||
tree.setAngle(-90)
|
||||
tree.drawTree(3, 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/logo/Snowflake.scala
Normal file
47
src/logo/Snowflake.scala
Normal file
@@ -0,0 +1,47 @@
|
||||
package logo
|
||||
|
||||
import hevs.graphics.TurtleGraphics
|
||||
|
||||
import java.awt.Point
|
||||
|
||||
class Snowflake(width: Int, height: Int) extends TurtleGraphics(width, height) {
|
||||
def drawFlakeSegment(n: Int, length: Double): Unit = {
|
||||
if (n == 1) {
|
||||
forward(length)
|
||||
return
|
||||
}
|
||||
|
||||
val third: Double = length / 3
|
||||
drawFlakeSegment(n - 1, third)
|
||||
turn(-60)
|
||||
drawFlakeSegment(n - 1, third)
|
||||
turn(120)
|
||||
drawFlakeSegment(n - 1, third)
|
||||
turn(-60)
|
||||
drawFlakeSegment(n - 1, third)
|
||||
}
|
||||
|
||||
def drawFlake(n: Int, length: Double): Unit = {
|
||||
val pos: Point = getPosition()
|
||||
val x: Double = pos.x - length / 2
|
||||
val y: Double = pos.y - math.sqrt(3) * length / 6
|
||||
jump(x.toInt, y.toInt)
|
||||
setAngle(0)
|
||||
drawFlakeSegment(n, length)
|
||||
turn(120)
|
||||
drawFlakeSegment(n, length)
|
||||
turn(120)
|
||||
drawFlakeSegment(n, length)
|
||||
turn(120)
|
||||
}
|
||||
}
|
||||
|
||||
object Snowflake {
|
||||
def main(args: Array[String]): Unit = {
|
||||
val win = new Snowflake(600, 600)
|
||||
win.penUp()
|
||||
win.jump(300, 300)
|
||||
win.penDown()
|
||||
win.drawFlake(5, 400)
|
||||
}
|
||||
}
|
||||
38
src/logo/TestLogo.scala
Normal file
38
src/logo/TestLogo.scala
Normal file
@@ -0,0 +1,38 @@
|
||||
package logo
|
||||
|
||||
import hevs.graphics.TurtleGraphics
|
||||
|
||||
import java.awt.Color
|
||||
|
||||
object TestLogo {
|
||||
def drawCircle(turtle: TurtleGraphics, radius: Double, resolution: Int = 24): Unit = {
|
||||
val angle: Double = 360.0 / resolution
|
||||
val side: Double = radius * math.sin(angle * math.Pi / 180)
|
||||
turtle.forward(-side / 2)
|
||||
for (_: Int <- 0 until resolution) {
|
||||
turtle.forward(side)
|
||||
turtle.turn(angle)
|
||||
}
|
||||
}
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
val turtle: TurtleGraphics = new TurtleGraphics(600, 600)
|
||||
turtle.drawLine(150, 300, 450, 300)
|
||||
|
||||
turtle.penUp()
|
||||
turtle.jump(300, 300)
|
||||
turtle.setAngle(0)
|
||||
turtle.forward(150 * math.sqrt(3) / 2)
|
||||
turtle.turn(150)
|
||||
turtle.penDown()
|
||||
for (_: Int <- 0 until 3) {
|
||||
turtle.forward(300)
|
||||
turtle.turn(120)
|
||||
}
|
||||
|
||||
turtle.jump(450, 300)
|
||||
turtle.setAngle(90)
|
||||
turtle.setColor(Color.RED)
|
||||
drawCircle(turtle, 150)
|
||||
}
|
||||
}
|
||||
41
src/logo/Tree.scala
Normal file
41
src/logo/Tree.scala
Normal file
@@ -0,0 +1,41 @@
|
||||
package logo
|
||||
|
||||
import hevs.graphics.TurtleGraphics
|
||||
|
||||
import java.awt.Point
|
||||
|
||||
class Tree(width: Int, height: Int, var angleStep: Double) extends TurtleGraphics(width, height) {
|
||||
def drawTree(n: Int, length: Double): Unit = {
|
||||
if (n > 1) {
|
||||
drawBranch(length)
|
||||
val pos: Point = getPosition()
|
||||
val angle: Double = getTurtleAngle()
|
||||
|
||||
turn(-angleStep)
|
||||
drawTree(n - 1, length * 0.8)
|
||||
jump(pos.x, pos.y)
|
||||
setAngle(angle)
|
||||
turn(angleStep)
|
||||
drawTree(n - 1, length * 0.8)
|
||||
} else {
|
||||
drawBranch(length)
|
||||
drawLeaf(length / 10)
|
||||
}
|
||||
}
|
||||
|
||||
def drawBranch(length: Double): Unit = {
|
||||
forward(length)
|
||||
}
|
||||
|
||||
def drawLeaf(length: Double): Unit = {
|
||||
|
||||
}
|
||||
}
|
||||
object Tree {
|
||||
def main(args: Array[String]): Unit = {
|
||||
val tree: Tree = new Tree(400, 400, 15)
|
||||
tree.jump(200, 400)
|
||||
tree.setAngle(-90)
|
||||
tree.drawTree(8, 60)
|
||||
}
|
||||
}
|
||||
5
src/magic_squares/Displayable.scala
Normal file
5
src/magic_squares/Displayable.scala
Normal file
@@ -0,0 +1,5 @@
|
||||
package magic_squares
|
||||
|
||||
trait Displayable {
|
||||
def display(g: Grid): Unit
|
||||
}
|
||||
53
src/magic_squares/GraphicsDisplay.scala
Normal file
53
src/magic_squares/GraphicsDisplay.scala
Normal file
@@ -0,0 +1,53 @@
|
||||
package magic_squares
|
||||
|
||||
import hevs.graphics.FunGraphics
|
||||
|
||||
import java.awt.{Color, Font}
|
||||
import javax.swing.SwingConstants
|
||||
|
||||
trait GraphicsDisplay extends Displayable {
|
||||
private var _win: Option[FunGraphics] = None
|
||||
private val WIDTH: Int = 400
|
||||
private val HEIGHT: Int = 400
|
||||
private val MARGIN: Int = 20
|
||||
private val FONT: Font = new Font("Arial", Font.PLAIN, 24)
|
||||
override def display(g: Grid): Unit = {
|
||||
if (_win.isEmpty) {
|
||||
_win = Some(new FunGraphics(WIDTH, HEIGHT))
|
||||
}
|
||||
val win: FunGraphics = _win.get
|
||||
win.clear()
|
||||
val size: Int = g.length
|
||||
|
||||
val w: Int = WIDTH - 2 * MARGIN
|
||||
val h: Int = HEIGHT - 2 * MARGIN
|
||||
val gridSize: Int = math.min(w, h)
|
||||
val cellSize: Int = gridSize / size
|
||||
val ox: Int = (WIDTH - gridSize) / 2
|
||||
val oy: Int = (HEIGHT - gridSize) / 2
|
||||
|
||||
win.drawRect(ox, oy, gridSize, gridSize)
|
||||
for (i: Int <- 1 until size) {
|
||||
win.drawLine(ox + cellSize * i, oy, ox + cellSize * i, oy + gridSize)
|
||||
win.drawLine(ox, oy + cellSize * i, ox + gridSize, oy + cellSize * i)
|
||||
}
|
||||
|
||||
for (y: Int <- 0 until size) {
|
||||
for (x: Int <- 0 until size) {
|
||||
val v: Int = g(y)(x)
|
||||
if (v != 0) {
|
||||
win.drawString(
|
||||
(ox + cellSize * (x + 0.5)).toInt,
|
||||
(oy + cellSize * (y + 0.5)).toInt,
|
||||
v.toString,
|
||||
FONT,
|
||||
Color.BLACK,
|
||||
SwingConstants.CENTER,
|
||||
SwingConstants.CENTER
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
win.syncGameLogic(60)
|
||||
}
|
||||
}
|
||||
156
src/magic_squares/MagicSquareSolver.scala
Normal file
156
src/magic_squares/MagicSquareSolver.scala
Normal file
@@ -0,0 +1,156 @@
|
||||
package magic_squares
|
||||
|
||||
abstract class MagicSquareSolver(initialGrid: Grid) extends Displayable {
|
||||
protected var _initial: Grid = initialGrid
|
||||
protected val _size: Int = _initial.length
|
||||
protected val SUM: Int = _size * (_size * _size + 1) / 2
|
||||
protected val DEBUG: Boolean = false
|
||||
|
||||
protected def print(grid: Grid): Unit = {
|
||||
for (y: Int <- 0 until _size) {
|
||||
println(grid(y).mkString(","))
|
||||
}
|
||||
}
|
||||
|
||||
protected def copy(grid: Grid): Grid = {
|
||||
return grid.map(_.clone())
|
||||
}
|
||||
|
||||
def solve(): Unit = {
|
||||
val sol: Option[Grid] = solveFrom(_initial, 0, 0)
|
||||
if (sol.isEmpty) {
|
||||
println("No solution")
|
||||
} else {
|
||||
print(sol.get)
|
||||
}
|
||||
}
|
||||
|
||||
private def solveFrom(grid: Grid, x: Int, y: Int): Option[Grid] = {
|
||||
if (DEBUG) println(s"Solving from $x, $y")
|
||||
if (DEBUG) print(grid)
|
||||
display(grid)
|
||||
if (!isValid(grid)) {
|
||||
if (DEBUG) println(" Grid is invalid")
|
||||
return None
|
||||
}
|
||||
if (y >= _size) {
|
||||
if (DEBUG) println(" Found solution")
|
||||
return Some(grid)
|
||||
}
|
||||
var values: Array[Int] = Array(_initial(y)(x))
|
||||
if (values(0) == 0) values = (1 to _size * _size).toArray
|
||||
if (DEBUG) println(s" Values to test: " + values.mkString("[", ", ", "]"))
|
||||
|
||||
val newGrid: Grid = copy(grid)
|
||||
var x2: Int = x + 1
|
||||
var y2: Int = y
|
||||
if (x2 >= _size) {
|
||||
x2 -= _size
|
||||
y2 += 1
|
||||
}
|
||||
|
||||
for (i: Int <- values) {
|
||||
if (DEBUG) println(s" Testing $i")
|
||||
newGrid(y)(x) = i
|
||||
val sol: Option[Grid] = solveFrom(newGrid, x2, y2)
|
||||
if (sol.isDefined) {
|
||||
if (DEBUG) println(" Found solution, collapsing call stack")
|
||||
return sol
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) println(s" No solution for this configuration")
|
||||
return None
|
||||
}
|
||||
|
||||
private def isValid(grid: Grid): Boolean = {
|
||||
val values: Array[Int] = grid.reduce((a, b) => a.concat(b)).filter(_ != 0)
|
||||
if (values.distinct.length != values.length) return false
|
||||
|
||||
val diag1: Array[Int] = new Array(_size)
|
||||
val diag2: Array[Int] = new Array(_size)
|
||||
for (i: Int <- 0 until _size) {
|
||||
val row: Array[Int] = grid(i)
|
||||
val col: Array[Int] = grid.map(_(i))
|
||||
diag1(i) = row(i)
|
||||
diag2(i) = col(_size - i - 1)
|
||||
|
||||
if (!isLineValid(row)) {
|
||||
if (DEBUG) println(s" -> row $i is invalid: " + row.mkString("[", ", ", "]"))
|
||||
return false
|
||||
}
|
||||
if (!isLineValid(col)) {
|
||||
if (DEBUG) println(s" -> column $i is invalid: " + col.mkString("[", ", ", "]"))
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (!isLineValid(diag1)) {
|
||||
if (DEBUG) println(s" -> diag1 is invalid: " + diag1.mkString("[", ", ", "]"))
|
||||
return false
|
||||
}
|
||||
if (!isLineValid(diag2)) {
|
||||
if (DEBUG) println(s" -> diag2 is invalid: " + diag2.mkString("[", ", ", "]"))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private def isLineValid(line: Array[Int]): Boolean = {
|
||||
val sum: Int = line.sum
|
||||
if (line.contains(0)) {
|
||||
if (sum > SUM) return false
|
||||
} else if (sum != SUM) return false
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
object MagicSquareSolver {
|
||||
def main(args: Array[String]): Unit = {
|
||||
val solver1: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||
Array(8, 0, 0),
|
||||
Array(0, 0, 7),
|
||||
Array(0, 9, 0)
|
||||
)) with TextDisplay
|
||||
solver1.solve()
|
||||
println()
|
||||
/*
|
||||
8,1,6
|
||||
3,5,7
|
||||
4,9,2
|
||||
*/
|
||||
|
||||
val solver2: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||
Array(9, 0, 0),
|
||||
Array(0, 0, 7),
|
||||
Array(0, 8, 0)
|
||||
)) with TextDisplay
|
||||
solver2.solve()
|
||||
println()
|
||||
/*
|
||||
no solution
|
||||
*/
|
||||
|
||||
val solver3: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||
Array(0, 0, 2),
|
||||
Array(0, 5, 7),
|
||||
Array(0, 0, 0)
|
||||
)) with GraphicsDisplay
|
||||
solver3.solve()
|
||||
/*
|
||||
4,9,2
|
||||
3,5,7
|
||||
8,1,6
|
||||
*/
|
||||
|
||||
val solver4: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||
Array(11, 0, 0, 20, 3),
|
||||
Array(4, 12, 0, 0, 16),
|
||||
Array(0, 5, 13, 21, 9),
|
||||
Array(10, 0, 0, 14, 22),
|
||||
Array(23, 6, 19, 2, 0),
|
||||
)) with GraphicsDisplay
|
||||
solver4.solve()
|
||||
}
|
||||
}
|
||||
9
src/magic_squares/TextDisplay.scala
Normal file
9
src/magic_squares/TextDisplay.scala
Normal file
@@ -0,0 +1,9 @@
|
||||
package magic_squares
|
||||
|
||||
trait TextDisplay extends Displayable {
|
||||
override def display(g: Grid): Unit = {
|
||||
for (y: Int <- g.indices) {
|
||||
println(g(y).mkString(","))
|
||||
}
|
||||
}
|
||||
}
|
||||
3
src/magic_squares/package.scala
Normal file
3
src/magic_squares/package.scala
Normal file
@@ -0,0 +1,3 @@
|
||||
package object magic_squares {
|
||||
type Grid = Array[Array[Int]]
|
||||
}
|
||||
Reference in New Issue
Block a user